Introduction
Welcome back! In the last article, we explored an overview of Android Architecture Components and patterns. Now, let’s zoom into two key players: ViewModel and Lifecycle. These tools help your app handle data and UI states like a pro—think surviving screen rotations or knowing when your app is active. Ready to dive in?
ViewModel: Saving Your Data
What is ViewModel and Why do we use it?
ViewModel is your app’s data guardian. It stores UI-related data that might otherwise disappear during configuration changes—like when a user rotates their screen. Without it, your app’s state resets, frustrating users.
Here’s an example: Imagine a counter app. You set a Text view to "0" and increment it with a Button. After five clicks, it shows "5." But rotate the screen, and boom—it’s back to "0" because the Activity restarts. ViewModel prevents this by keeping the count safe across these changes.
How to use ViewModel
Step 1. add the dependency.
Paste this line in your build.gradle
(Module level)
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
Note: If using Jetpack Compose, use lifecycle-viewmodel-compose instead.
Step 2. Make a ViewModel class.
Make a class that extends ViewModel to hold your data:
class MyViewModel : ViewModel() {
var count by mutableStateOf(0) // State in ViewModel
private set // Only ViewModel can modify it
fun updateCount() {
text++ // Update state
}
}
Step 3. Set up in your App.
Now use the MyViewModel
class in your app to show the count value on your UI.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp(viewModel: MyViewModel = viewModel()) {
//viewModel() function provides the instance of MyViewModel.
Column(modifier = Modifier.padding(16.dp)) {
Text(text = "${viewModel.count}")
Button(onClick = { viewModel.updateCount() }) {
Text("Click Me")
}
}
}
Run it, click a few times, and rotate the screen—the count sticks around!
Lifecycle: Tracking Your App’s States
LEvery Activity or Fragment has a lifecycle—stages like creation, visibility, or destruction. Think of it like a human life: born (onCreate), active (onResume), resting (onPause), or gone (onDestroy). Knowing these states lets you control what happens when—like saving data before the app closes.
Here’s a quick example:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("Lifecycle", "onCreate called")
setContent {
MyApp()
}
}
override fun onStart() {
super.onStart()
Log.d("Lifecycle", "onStart called")
}
override fun onResume() {
super.onResume()
Log.d("Lifecycle", "onResume called")
}
override fun onPause() {
super.onPause()
Log.d("Lifecycle", "onPause called")
}
override fun onStop() {
super.onStop()
Log.d("Lifecycle", "onStop called")
}
override fun onDestroy() {
super.onDestroy()
Log.d("Lifecycle", "onDestroy called")
}
}
Check your Logcat as you open, minimize, or close the app—each state logs a message!
Lifecycle Observer
Want to react to lifecycle changes without overriding methods? Use a Lifecycle Observer. Here’s how:
Here is how we use Lifecycle Observer and Owner.
class MyObserver : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
Log.d("LifecycleObserver", "Activity started!")
}
override fun onStop(owner: LifecycleOwner) {
super.onStop(owner)
Log.d("LifecycleObserver", "Activity stopped!")
}
}
In above code, we are inheriting DefaultLifecycleObserver
to define an observer. Inside the observer we are implementing our tasks.
Now, we need to attach the observer with our activity, here is how do we do it.
@Composable
fun MyComposable() {
val lifecycleOwner = LocalLifecycleOwner.current
val observer = remember { MyObserver() }
DisposableEffect(lifecycleOwner) {
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
Text("Hello, Lifecycle!")
}
Here, LocalLifecycleOwner.current
provides the instance of Lifecycle Owner of current activity.
DisposableEffect()
is a side-effect function that gets created when the composable starts and gets destroyed when the activity gets disposed.
lifecycleOwner.lifecycle.addObserver(observer)
it is adding the observer we made above.
lifecycleOwner.lifecycle.removeObserver(observer)
it removes the observer when activity gets disposed.
Conclusion
We’ve unlocked ViewModel to preserve data and Lifecycle to track UI states. Together, they make your app resilient and smart. Next up, we’ll tackle LiveData to keep your UI in sync with changing data. See you there!
Top comments (1)
Linking something (VM is a android recommended architecture component, for storing
UI states
and simple business logic) or redirect to official docs would be great for absolute beginners apart from this your high level example is great.