DEV Community

Ahmed Rizwan
Ahmed Rizwan

Posted on • Edited on

2 1

Android ViewModels: Saving State across Process Death

A misconception among some android developers is that the purpose of using ViewModels is state persistence — it’s actually partly true — they do help in saving state across configuration change (e.g. device rotation) but not process death. So if Android kills your app (let’s say because of low memory), then your app state is lost.

So depending on whether you want to persist your state across process death or not — you can either use onSaveInstanceState in your Fragments/Activities or the new SavedStateHandle in your ViewModels.

Ok so why SavedStateHandle and why save/handle states in ViewModels?

Well if you handle your state (for process death) in Activities or Fragments — that’ll add extra verbosity and will cause tight coupling between state-handling & activity/fragment code. Handling your state via ViewModels solves this issue.

Using SavedStateHandle

Add lifecycle-viewmodel-savedstate dependency

dependencies {
  def lifecycle_version = "2.2.0" // currently the latest version
  // Saved state module for ViewModel
  implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
}
Enter fullscreen mode Exit fullscreen mode

Add SavedStateHandle property in your ViewModel

class MainViewModel(val state: SavedStateHandle) : ViewModel() {

}
Enter fullscreen mode Exit fullscreen mode

Initialize your ViewModel using SavedStateViewModelFactory

class MainFragment : Fragment() {

   private val viewModel: MainViewModel by viewModels {
      SavedStateViewModelFactory(application, activity)
   }

Enter fullscreen mode Exit fullscreen mode

Save and restore state

The SavedStateHandle has methods for setting/getting values.

  • get(String key)
  • contains(String key)
  • remove(String key)
  • set(String key, T value)
  • keys()

You can save/restore primitives, bundles and parcelables.
Saving is as easy as:

// In your viewmodel
fun saveName(name: String) {
    state.set("Name", name)
}
// In your fragment
viewModel.saveName("Ahmed Rizwan")
Enter fullscreen mode Exit fullscreen mode

And restoring:

// In your viewmodel
fun getName(): String? {
    state.get<String>("Name")
}
// In your fragment 
val name = viewModel.getName()
Enter fullscreen mode Exit fullscreen mode

Restore state as a LiveData

If you want to restore your data as LiveData, theres a getter for that as well.

// In your viewmodel 
val nameLiveData = state.getLiveData<String>("Name")
// In your activity/fragment
viewModel.nameLiveData.observe(this) { name ->
   // handle changes
}
Enter fullscreen mode Exit fullscreen mode

And that’s it — make sure to handle all your states!
Happy coding!

Sentry mobile image

Improving mobile performance, from slow screens to app start time

Based on our experience working with thousands of mobile developer teams, we developed a mobile monitoring maturity curve.

Read more

Top comments (0)

Sentry growth stunted Image

If you are wasting time trying to track down the cause of a crash, it’s time for a better solution. Get your crash rates to zero (or close to zero as possible) with less time and effort.

Try Sentry for more visibility into crashes, better workflow tools, and customizable alerts and reporting.

Switch Tools

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay