SavedStateHandle does not persist data

5.9k Views Asked by At

I followed the instructions in the following page and created a viewModel, but SavedStateHandle does not work when I close the app and open it again.

Here is the page:

Saved State module for ViewModel

Here is my view model class:

class UserViewModel(private val state : SavedStateHandle) : ViewModel(){
    val userId: LiveData<String> by lazy {
         state.getLiveData("userId")
    }
    fun setUserId(userId : String) {
        state["userId"] = userId
    }
    val user : User by lazy {
        User("")
    } }

Here is how I use the viewModel in my activity.

val userViewModel :  UserViewModel by viewModels()

I even tried this one in my activity, but this did not work either!

val userViewModel: UserViewModel by viewModels {
            SavedStateViewModelFactory(
                application,
                this
            )

What should I do to persist data in the SavedStateHandle? I mean, after opening the app state is still empty.

3

There are 3 best solutions below

5
On

Within the documentation that you linked you can read that, under User-initiated UI-state dismissal:

The user's assumption in these complete dismissal cases is that they have permanently navigated away from the activity, and if they re-open the activity they expect the activity to start from a clean state. The underlying system behavior for these dismissal scenarios matches the user expectation - the activity instance will get destroyed and removed from memory, along with any state stored in it and any saved instance state record associated with the activity.

from https://developer.android.com/topic/libraries/architecture/saving-states#use_onsaveinstancestate_as_backup_to_handle_system-initiated_process_death

So you have misunderstood the intentions and scope of SavedStateHandle and ViewModel. If restoring state after user initiated UI-state dismissal is really important to your app then I suggest starting with focussing on preserving state to disk (DB, file, SharedPreferences, etc) and restoring when appropriate - then later on look at facilitating smoother UX by leveraging features such as SavedStateHandle in ViewModel.

0
On

SavedStateHandle is a wrapper over onSaveInstanceState. So it has the same duration as onSaveInstanceState: it would be used for configuration changes and process death (low memory condition initiating killing your process while retaining the task stack as history, with intents and extras and all that).

As ViewModel survives config changes, you'd see the benefits across process death. So it's when you navigate out of your app by placing it in background, getting a key from your email client for example, coming back, and you didn't lose your state in your ViewModel.

It's not a general purpose persistence solution. It's to ensure that your app behaves correctly even when it's not the only app that the user uses.

If you want to persist data across phone reboots or force stop or quitting the app or task clear, then use SharedPreferences or some similar disk-based persistence solution.

0
On

---- Edit: ----

The system seems to free memory in two steps and SavedStateHandle only persist data during the first step:

  1. System kills the process. App remains in the recents screen. Data is persisted by SavedStateHandle (or by the view in savedInstanceState in the case of EditText, see the codelab).
  2. System finishes the app. App is removed from the recents screen. Data in SavedStateHandle is gone, just as if user finished the app.

Conclusion: If you want to persist your data during step 2 then use something more persistent than SavedStateHandle.

---- end edit ----

I did something similar as in the code lab (https://developer.android.com/codelabs/android-lifecycles#6).

Just as described by the OP it doesn't make any difference (for me) to store a LiveData in the SavedStateHandle. When system finishes the app (edited, original text was: kills the process) the LiveData stored in the SavedStateHandle is gone.

I didn't change any dependencies. I used a template in Arctic Fox 2020.3.1 (the bottom navigation template). It compiled fine to add SavedStateHandle to a AndroidViewModel subclass, but it doesn't save the LiveData.