“Composing” the Flutter counter app with Jetpack Compose: Part 2

In Part 1 we talked about how one can build a counter app using Jetpack compose. We talked about how you can change layout elements, what is going on when you try to update the UI, and manage state inside an app.
Let’s go through some of the terms you should have an idea about before we move ahead with the article:
- @Composable annotation
- @Preview annotation
- Recomposition
- mutableStateOf
- remember
- rememberSaveable
Alright, if you feel that you have some idea about the terms mentioned above, feel free to read ahead. If not, please read Part 1 because…
State in Jetpack Compose:
For a composable to read state changes, Jetpack requires it to be of type State<T>. Some common observable types that you might want to use instead mutableStateOf are:
As you develop reusable composables, you often want to expose both a stateful and a stateless version of the same composable.
The stateful version is convenient for callers that don’t care about the state, and the stateless version is necessary for callers that need to control or hoist the state.
The Part 1 we had Stateless composables in play. Both CenterText and MyFab are Stateless.
Now, let’s see how adding a ViewModel in the picture would help us manage State. We will be using ViewModel to expose the state in an observable holder (like LiveData or Flow) and also to handle events that affect that state.
First, add these dependencies to your build.gradle file:
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"implementation "androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha05"
This will let you access both observeAsState and viewModel() in your MainActivity.kt file.
Next, in your project, create a new Kotlin class by the name of CounterViewModel. It should look something like this:
Next, in your MainAcitivity.kt file, update your MainView composable like this:
@Preview(showBackground = true, showSystemUi = false)
@Composable
fun MainView(counterViewModel: CounterViewModel = viewModel()) {
val count by counterViewModel.counterLiveDate.observeAsState(0)
Scaffold(
topBar = {
TopAppBar(
title = {
Text(text = "CounterApp")
},
)
},
floatingActionButton = {
MyFab {
counterViewModel.increaseCounter()
}
},
content = {
CenterText(count)
},
)
}
New imports added to MainActivity should be:
import androidx.compose.runtime.livedata.observeAsState
import androidx.lifecycle.viewmodel.compose.viewModel
Here, we pass the viewmodel to the MainView composable to get access to the LiveData that the UI can read as the State and update itself as and when the value changes.
Rest everything remains the same as both the other composables were Stateless i.e. the State was managed by the MainView composable.
Rebuild the app and Voila!, the counter increases when you tap the FAB.
How many claps does this article deserve?
If you find this article useful, please click the 👏 button and share to help others find it! Feel free to clap many times (10💥, 20💥 , or maybe 50💥 ?) It fuels my focus to write more of it.
Connect with me on LinkedIn or say hi on Twitter, mentioning this article. You can drop an e-mail at annsh29@gmail.com as well.
Check out my series on various Flutter widgets here -