Jetpack compose: How to use ViewModel state

This code demonstrates how to manage UI state using ViewModel in a Jetpack Compose application. Here's a breakdown of the code:

1. Setting Up the Activity (MainActivity.kt):

  • The MainActivity class extends ComponentActivity and defines the application's entry point.
  • In onCreate, setContent composes the UI hierarchy using a custom theme (ComposeStateTheme).
  • The Scaffold composes the overall layout with a top bar, content area, and background color.

2. Main Content with ViewModel (MainContent.kt):

  • The MainContent composable defines the central content of the screen.
  • It uses viewModel to access an instance of MyViewModel.
  • counter observes the _counter state flow from the ViewModel and stores the current value in a composable state.
  • A Column arranges the UI elements:
    • A Text displays the current counter value from the ViewModel.
    • A Button triggers the incrementCounter function in the ViewModel.

3. ViewModel for Counter State (MyViewModel.kt):

  • MyViewModel extends ViewModel and manages the application state.
  • It uses MutableStateFlow to hold the counter value (_counter).
  • counter exposes the state flow as a read-only StateFlow for composables to observe.
  • incrementCounter increases the internal counter value by 1.

4. Gradle Dependencies:

  • The build.gradle file includes necessary dependencies:
    • lifecycle-viewmodel-ktx: Provides core ViewModel functionality.
    • lifecycle-viewmodel-compose: Integrates ViewModel with Jetpack Compose.

Summary

This example showcases how to separate UI state management from the composable UI using ViewModel. The ViewModel holds the counter value (_counter) and exposes it as a state flow (counter). The MainContent composable observes this state flow to display the counter and trigger updates by calling incrementCounter on the ViewModel. This separation keeps the UI logic clean and enables the ViewModel to survive configuration changes, ensuring state persistence.


MainActivity.kt

package com.cfsuman.composestate

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.cfsuman.composestate.ui.theme.ComposeStateTheme


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeStateTheme {
                Scaffold(
                    topBar = { TopAppBar(
                        title = {
                            Text(text = "Compose - ViewModel State")
                        }
                    )},
                    content = { MainContent() },
                    backgroundColor = Color(0xFFEDEAE0)
                )
            }
        }
    }
}


@Composable
fun MainContent() {
    val viewModel = viewModel<MyViewModel>()
    val counter = viewModel.counter.collectAsState()

    Column(
        Modifier.fillMaxSize().padding(24.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "${counter.value}", fontSize = 40.sp)
        Button(onClick = { viewModel.incrementCounter() }) {
          Text(text = "Increment Counter")
        }
    }
}
MyViewModel.kt

package com.cfsuman.composestate

import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.*

class MyViewModel:ViewModel() {
    private val _counter = MutableStateFlow(0)
    val counter = _counter.asStateFlow()

    fun incrementCounter(){
        _counter.value +=1
    }
}
build.gradle [app]

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.0-alpha06"
    implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha06"
}
More android jetpack compose tutorials