Build: Counter Screen
A simple screen that shows a number and a button to increase it. The number is stored in a ViewModel to keep state across screen rotations.
Target UI
------------------- | Counter: 0 | | | | [Increase] | -------------------
------------------- | Counter: 0 | | | | [Increase] | -------------------
import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.lifecycle.ViewModel import androidx.lifecycle.viewmodel.compose.viewModel class CounterViewModel : ViewModel() { // TODO: Add counter state here } class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: android.os.Bundle?) { super.onCreate(savedInstanceState) setContent { CounterScreen() } } } @Composable fun CounterScreen(counterViewModel: CounterViewModel = viewModel()) { // TODO: Display counter and button }
import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.lifecycle.ViewModel import androidx.lifecycle.viewmodel.compose.viewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow class CounterViewModel : ViewModel() { private val _counter = MutableStateFlow(0) val counter: StateFlow<Int> = _counter.asStateFlow() fun increment() { _counter.value += 1 } } class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: android.os.Bundle?) { super.onCreate(savedInstanceState) setContent { CounterScreen() } } } @Composable fun CounterScreen(counterViewModel: CounterViewModel = viewModel()) { val count by counterViewModel.counter.collectAsState() Surface(modifier = androidx.compose.ui.Modifier.fillMaxSize()) { Column( horizontalAlignment = androidx.compose.ui.Alignment.CenterHorizontally, verticalArrangement = androidx.compose.foundation.layout.Arrangement.Center, modifier = androidx.compose.ui.Modifier.fillMaxSize() ) { Text(text = "Counter: $count", style = MaterialTheme.typography.headlineMedium) Spacer(modifier = androidx.compose.ui.Modifier.height(16.dp)) Button(onClick = { counterViewModel.increment() }) { Text("Increase") } } } }
We use a MutableStateFlow in the CounterViewModel to hold the counter state. This allows the state to survive configuration changes like screen rotations because ViewModel lives longer than the Activity.
The counter is exposed as a read-only StateFlow. The increment() function updates the counter value.
In the CounterScreen composable, we collect the counter state as Compose state using collectAsState(). This makes the UI automatically update when the counter changes.
The UI shows the current counter value in a Text and a button labeled "Increase" that calls increment() in the ViewModel.
------------------- | Counter: 0 | | | | [Increase] | -------------------
ViewModel in Android development?class MyViewModel : ViewModel() {
private val _count = MutableLiveData(0)
val count: LiveData<Int> = _count
fun increment() {
_count.value = (_count.value ?: 0) + 1
}
}count after calling increment() twice starting from initial state?class SampleViewModel : ViewModel() {
val data = MutableLiveData<String>()
fun updateData(newValue: String) {
data.value = newValue
}
fun getData(): String {
return data.value
}
}Pass the test and this pattern moves unknown