Last week, Google released ViewModel Savedstate 1.0.0. Its documentation states:

ViewModel objects can handle configuration changes so you don't need to worry about state in rotations or other cases. However, if you need to handle system-initiated process death, you may want to use onSaveInstanceState() as backup.

When an Activity is destroyed because of memory pressure, the state of the ViewModel is not saved. When the Activity is recreated, the ViewModel will have lost data that was only stored in memory. This is a problem that we often encounter, so we came up with a custom solution. But now Google released its official library to handle this case and I was happy to play with it.

There is already a nice deep-dive article about it, but I wanted to take a step further. I wanted to make it so easy that you don’t even have to think about saving your state.

Define ViewModel variables like you are used to

With my collection of ViewModel SavedState Helpers, you can define your ViewModel like if it was a local variable.

// Import the library
import ch.liip.viewmodelsavedstatehelpers.*

// Define a ViewModel that takes a SavedStateHandle in argument
class MainViewModel(handle: SavedStateHandle) : ViewModel() {
    // Simple string that is saved in the SavedState
    var manualText by handle.delegate<String?>()

    // MutableLiveData that is saved in the SavedState
    val liveDataText by handle.livedata<String?>()
}

You can then use the ViewModel like you would do usually. Your data is saved and restored automatically!

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // Obtain the ViewModel with SavedStateVMFactory
    viewModel = ViewModelProviders.of(this, SavedStateVMFactory(this)).get(MainViewModel::class.java)

    // Observe the livedata
    viewModel.liveDataText.observe(this, Observer {
        liveDataText.setText(it)
    })

    // Save the values
    button.setOnClickListener {
        viewModel.liveDataText.value = liveDataText.text.toString()
    }
}

How does it work ?

This is heavily related to our work on SweetPreferences. I basically use Kotlin delegated properties to wrap the calls into a SavedStateHandle, which is the main class offered by the ViewModel Savedstate library.

Take a look at the only file to see the whole code. Then install the library from Github and enjoy your peace of mind when it comes to saving state!