3

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.

a.toraby
  • 3,232
  • 5
  • 41
  • 73

3 Answers3

4

---- 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.

solgule
  • 51
  • 2
2

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.

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
1

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.

straya
  • 5,002
  • 1
  • 28
  • 35
  • 1
    Thanks for your answer. So what is the usage of `SavedStateHandle`? my view model works the same, with and without it! For example, for handling orientation changes, I do not need `SavedStateHandle`. So when should I use it? – a.toraby Oct 14 '21 at 07:58
  • But I am pretty sure that it is for saving the state even after the process being killed. Take a look at this codelab: https://developer.android.com/codelabs/android-lifecycles#6. Is it wrong? – a.toraby Oct 14 '21 at 08:35
  • 2
    OK, I reviewed it again, and now I am quite sure that you are wrong: https://developer.android.com/topic/libraries/architecture/viewmodel-savedstate#savedstatehandle. It is used to retain values across process death – a.toraby Oct 14 '21 at 08:57
  • 1
    It comes down to how you are killing the app. If you are using the command line to kill process akin to the OS doing it then yes SavedStateHandle should play a role. If the user did it (you being the user) then like the table in my link shows it won't play a role. – straya Oct 14 '21 at 23:38
  • It appears to me that it saves the data in the normal running of the app fairly well (as others have described), but as we develop apps, we kill them outside of the normal lifecycle, and it appears to not work. If set an emulator to always kill activities, and switch to another app, then back to mine, it works. When I relaunch the app from the IDE, it does not. But I believe that's to be expected. – johngray1965 Mar 23 '23 at 17:10