"persistent state" vs. "current state"
Asked Answered
V

3

15

Attempting to decide (for my application) what to save in onPause() and what to save in onSaveInstanceState(), I combed the entire SO for hints and clear guidelines.

If I understand correctly, onSaveInstanceState() is best for saving "runtime changes" or "current state" (whatever that means), while onPause() is best for saving "persistent state" (whatever that means).

I am still having difficulty deciding what in my application constitutes "persistent state" vs. "current state". For example, while user preferences are clearly persistent, do I need to save them in onPause() when they are always saved automatically by the Android UI framework when the user changes them?

Do class data members need to be saved in onSaveInstanceState()? Do I need to do that for every class in my application?

I am confused.

Can you bring real-world examples of what must be saved in onPause() and what must be saved in onSaveInstanceState()? Except for device configuration changes, that is.

--

Some new insights, after my question has been answered:

  • onSaveInstanceState's Bundle is not written to anything, and it's not persistent in any way.
  • onSaveInstanceState's Bundle data will only be held in memory until the application is closed.
Vanda answered 8/8, 2012 at 23:20 Comment(3)
"Except for device configuration changes"... what does that mean?Proximal
This is related to orientation type changes.Rakia
@AlexLockwood The word "Except" is a link to what it means. The almost boring example is orientation type changes, but it may be something else? (e.g. USB keyboard connected, Internet connectivity established, etc.)Vanda
M
10

You do not need to store user preferences in onPause because as you say, the framework does that for you.

To distinguish between persistent data vs state information, think of a text editor application.

Persistent data

Let's say the user has typed a couple words and then exits the app. The user didn't explicitly tell us to save that data to a file, but it sure would be nice to store that data away for when they come back. This is persistent data and you want to store it away in onPause().

State data

Similarly, say you have 2 tabs and a variable that tracks which tab is currently selected. This is state data that you'd store in onSaveInstanceState().

Gray matter

Finally imagine you have a class in the editor that keeps track of the number of characters and number of lines in the editor. This is state data, you could store it in onSaveInstanceState() or you can throw it away and simply recalculate it when you start up again. Whether you throw it away might depend on how long it takes to calculate, for instance if you could prevent a network request by storing data, do so.

Further thoughts

By playing with your app it should be obvious if there's an area where you failed to squirrel the right data away. Be sure to do things like hit the home button and then close out your app from the device manager. This will let you hit the corner cases where your app is shut down rather than just paused.

If your UI state is consistent across lifecycle events and your user data remains, good job.

Edit based on comment

I think there are 2 pieces of criteria here to determine when/what to save.

The first is quite subjective - Do you want to save data at all? There's truly nothing forcing you to save state or data. Will saving this information make for a better user experience? If you are writing an email and trying to copy/paste text from another app, losing your half typed email every time the app gets closed would be frustrating.

The second piece, determining what to save depends on whether you can reconstruct your UI state based on the data that you have. For instance, if you have saved text data then that must mean that the user was editing text. So now we know to switch to the edit text tab and fill in the saved text.

Generally speaking, if the desire is that you want to return the user to the same place they left off then you need to think about the state data required to get back to that point. Imagine a pristine loaded version of your app

  • what data needs to change to turn that into the last state the user saw?
  • what data do you need to store to get back here?

This is really how android works, your activity is destroyed and recreated and it is your job to set the pieces in motion again (if you choose to do so).

Mildamilde answered 9/8, 2012 at 0:24 Comment(6)
This is exactly the type of answer I needed, so accepting. Still, to make things a bit clearer: Why is the classification of the tab selected different from user typed words? Is this because typed words are critical data while tab selected is "nice to have"? Is this the criteria for deciding what's persistent and what's state? (BTW, I've seen editors that persistently save the tab selected, even in between reboots).Vanda
I think there are 2 pieces of criteria here. The first is quite subjective - will saving this information make for a better user experience? If you are writing an email and trying to copy/paste text from another app, losing your half typed email every time you switch apps would be frustrating. The second piece is whether you can reconstruct your UI state based on data you have - if you have saved text data that must mean that the user was editing text, switch to that tab and fill in the saved text.Mildamilde
P.S. Saving date in onPause() is only half the story. Cancelling or Stopping certain operations seem to be the other half, as exemplified in the CookieSyncManager documentation. Or can this be regarded as storage as well?Vanda
Cookie syncing is specific to you using a webview in your app and wanting to sync cookies to disk so that they don't accidentally get purged from cache. But generally speaking, you should take care to stop any auxiliary threads that may be spun up.Mildamilde
"stop any auxiliary threads that may be spun up" -- in onStop(), right? Lastly, to make things even more complicated, pausing an activity via the home button is not the same as pausing it via the back button which is different from pausing it by starting another Intent? That link suggests that in some types of pausing onSaveInstance() will be called while in others it will not.Vanda
I tend to stop things in onPause, again it depends on what you're doing. A thread that calculates physics equations for a simulation displayed on the UI? Stop it in onPause(). A thread that is providing GPS routing... The back button closes your app rather than pausing it. onPause is always the signal that you are going to the background possibly to never return, I'd bank on this, onStop() isn't called in all circumstances like when the OOM killer nom noms you. I rarely use onStop.Mildamilde
R
6

Here is answer. You can save state in three different ways.

1) Subclassing app (not a good idea). 2) SharedPreferences (good for simple data, quick and reliable) 3) SQLite Database (More complex, also reliable).

Now to answer your question. There are really NO guarantees with android. At any time it can and may destroy your application without calling any particular function before it does so. So if there is data that is vital to save, the answer is save it as soon as you get it. There is usually not much advantage to saving something later, if you know you are going to need something save it immediately.

onSaveInstanceState() is just for saving temporary variables related to layout or orientation changes.

In summary persistent state/data (that should survive a crash), should be saved ASAP, don't wait for onPause(), because there are no guarantees. That's the reality.

Rakia answered 8/8, 2012 at 23:38 Comment(2)
Great clarifications. Thanks! (I'm going to highlight what I believe are key tips)Vanda
Great clarifications but onPause is guaranteed to be called before app is killed......there are logical statements which we can draw this inference from 1. never a resumed application will be killed by android 2. application will get into non-resumed(paused state) only when application onPause has been called please let me know if i am missing something hereOwen
P
0

The case I have is a game, where I want to save persistant data to a gameserver.

As this may take awhile, I find it not a good thing to try and save in onPause, but rather in onStop.

According to the tests I have done, onStop seem to be able to run in the background while onPause blocks, atleast that is the case when I press home (tested with a simple for 1 to 10m loop in onPause and onStop). Can anyone confirm this blocking theory ?

onStop NEEDS Honeycomb up (api11+), because before that version you can get killed before onClose is called.

See here and look for killable in the table - If reality matches the documentation is another question :).

Phosphoric answered 27/8, 2012 at 18:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.