19

I know this question has been asked a million times, I myself though that I already knew the answer and that the correct one was that the only guaranteed call is to onPause(), so you should save your data there.

However, in many places of android documentation they always suggest not doing heavy work (such as writing data in database) in the onPause() method as it will delay the transition between the activities.

According to Android Developer Guide in Table 1

onPause(): This method is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, and so on. It should do whatever it does very quickly, because the next activity will not be resumed until it returns.

Killable: YES

Then according to Android Developer Reference Guide in the similar table.

It says the same thing but:

Killable: Pre-HONEYCOMB

And they add a little note that says:

Be aware that these semantics will change slightly between applications targeting platforms starting with HONEYCOMB vs. those targeting prior platforms. Starting with Honeycomb, an application is not in the killable state until its onStop() has returned. This impacts when onSaveInstanceState(Bundle) may be called (it may be safely called after onPause() and allows and application to safely wait until onStop() to save persistent state.


Killable

Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed.

FOR POST-HONEYCOMB (i dont care about earlier versions): So, is it OK to assume that any Android device (including different ROMS) will ensure a call to onStop on the activity? And this is the best place to make any time consuming storage writing of the App?

Note: This is extremely confusing as most answers here, sites, books, and even online android tests take as a correct answer that you should save it in onPause and NOT in onStop.

klifa
  • 671
  • 1
  • 8
  • 27
  • 2
    See https://developer.android.com/about/dashboards/index.html for current device distribution. Pre-honeycomb devices account for only 7.5% as of April 2015, so to keep the logic simpler you may want to target API 15+ and ignore the older behavior. Or just do it all in `onPause()` and call it a day. – fadden Apr 07 '15 at 01:22
  • 1
    fadden, this comment does not help at all – klifa Apr 07 '15 at 14:57
  • Thank you for clarifying that you're not actually interested in pre-honeycomb behavior. – fadden Apr 07 '15 at 15:45
  • I hate this question and the reason is i have seen this question in almost 7-10 android interviews as a multiple choice question and the surprise is that MCQ contained `a) onStop() b) onPause() c) onDestroy() d) onActivityKill() `options.What should be the answer? – Piyush Kukadiya Mar 13 '17 at 16:27

3 Answers3

21

When to save data to database, onPause() or onStop()?

Either. They are nearly identical, particularly on Android 3.0+.

If the activity that is taking over the foreground is a typical full-screen activity, so that the earlier activity is no longer visible, onPause() and onStop() will be called in rapid succession.

If the activity that is taking over the foreground is themed to be more like a dialog, where the earlier activity is still visible, onPause() will be called, but not onStop(), until such time as the activity is no longer visible (e.g., user now presses HOME).

Most apps aren't worried about the "themed to be more like a dialog" scenario, in which case onPause() and onStop() are called one right after the next, and you can fork your background thread to save your data in whichever of those makes sense to you.

However, in many places of android documentation they always suggest not doing heavy work (such as writing data in database) in the onPause() method as it will delay the transition between the activities.

The same is true of onStop(), as both of those methods are called on the main application thread.

So, is it OK to assume that any Android device (including different ROMS) will ensure a call to onStop on the activity?

Both onPause() and onStop() will have the same characteristics from the standpoint of process termination. Either both should be called (normal case) or neither will be called (e.g., you crash, the battery pops out the back of the phone).

And this is the best place to make any time consuming storage writing of the App?

Either onPause() or onStop() are fine places to trigger the work, done on a background thread, to persist your data. If you prefer to do that work in onStop(), you are absolutely welcome to do so. Personally, I'm an onPause() kind of guy.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • If it is a time consuming operation or any operation you want to do it just once or as little as possible it might be best to do it in onStop() as it has the exact same result and it will be called less frequently right? – klifa Apr 08 '15 at 01:36
  • 5
    For anyone looking for info on when `onPause()` and `onStop()` are _not_ "nearly identical", see http://developer.android.com/guide/components/activities.html#CoordinatingActivities. To paraphrase: "When transitioning from one activity to another, the first activity is not completely stopped before the second one is created". – Vicky Chijwani Jan 06 '16 at 09:40
  • @VickyChijwani: From the standpoint of what is being discussed in the question, they are nearly identical. – CommonsWare Jan 06 '16 at 12:46
  • @CommonsWare you're right, I was just adding more info for anyone interested. – Vicky Chijwani Jan 06 '16 at 12:48
  • 1
    @CommonsWare - but isn't the point of `onPause` that it *is* called in *some* situations where `onStop` is not called? Hence official statements like "you should avoid performing CPU-intensive work during onPause(), such as writing to a database, because it can slow the visible transition to the next activity (you should instead perform heavy-load shutdown operations during onStop())." https://developer.android.com/training/basics/activity-lifecycle/pausing.html – ToolmakerSteve Sep 22 '16 at 13:19
  • @ToolmakerSteve: "but isn't the point of onPause that it is called in some situations where onStop is not called?" -- yes, for cases where the activity is only paused. For example, on Android 7.0+, in a multi-window scenario, your activity will be paused but not stopped if the user taps on the activity in the other pane, transferring focus to it. You should not be doing CPU-intensive work in *either* `onPause()` *or*` `onStop()`, but rather in a background thread. Whether you trigger that work from `onPause()` or `onStop()` depends upon the work in question. – CommonsWare Sep 22 '16 at 13:23
  • @CommonsWare I hate this question and the reason is i have seen this question in almost 7-10 android interviews as a multiple choice question and the surprise is that MCQ contained `a) onStop() b) onPause() c) onDestroy() d) onActivityKill()` options. – Piyush Kukadiya Mar 13 '17 at 16:26
2
  • If you want more safety, storage in onPause.
  • If your data is so big that you have to storage it for several seconds, you may open a background Service (e.g. IntentService) to save.
  • You can also check the system version in your code and choose when to save. if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.ICE_CREAM_SANDWICH){}
  • In most situations this rule of when to save will not be changed by some customed os. But of course there can be some other os which certainly changed it. So the most important thing in android development is that u need to know that everything can be different in different phones.
ch271828n
  • 15,854
  • 5
  • 53
  • 88
  • 2
    Thanks for your answer, the IntentService would probably be a good idea. However, still, for devices post-honeycomb (edited my question), the same question persist. Why is "more safety" to do it in the onPause, doing it in onStop would be also safe, plus, as it wont block UI i wont need to use a background service to save the data right? – klifa Apr 07 '15 at 14:58
  • 2
    @klifa: Both `onPause()` and `onStop()` are called on the main application thread. You need to use a background thread in either case. The difference of whether to use an `IntentService` versus a plain `Thread` is mostly in the time that your I/O takes. If it will be more than a second or so, I would use the `IntentService`, so there is a signal to Android that your process is still doing work, even if the `onPause()` or `onStop()` are being triggered by your app moving to the background, where it is eligible to be terminated. – CommonsWare Apr 07 '15 at 16:18
  • 1
    @CommonsWare - can you provide any link or evidence that it is necessary to do the work on a background thread, for `onStop`, if the work is up to perhaps 200 ms? Alternatively, any evidence that having a background thread running will be considered by OS when deciding whether it is safe to terminate your app? I have been doing some file writing in OnStop in foreground, to be sure it was completed. – ToolmakerSteve Sep 22 '16 at 13:26
  • 1
    @ToolmakerSteve: "can you provide any link or evidence that it is necessary to do the work on a background thread, for onStop, if the work is up to perhaps 200 ms?" -- you should be spending <1ms on any callback from the framework, to avoid jank. [~200ms will drop ~12 frames at 60fps](https://developer.android.com/training/testing/performance.html). [`StrictMode`](https://developer.android.com/reference/android/os/StrictMode.html), for example, will point out that disk I/O on the main application thread is inappropriate, and has done so since API Level 9. – CommonsWare Sep 22 '16 at 13:30
  • 1
    @ToolmakerSteve: "any evidence that having a background thread running will be considered by OS when deciding whether it is safe to terminate your app?" -- it won't be. However, your app is only just exiting the foreground, and so it is unlikely that its process will be terminated in the next 200ms. If you are concerned about this, use an `IntentService` rather than a plain thread. Usually, I don't get to that level of concern until closer to the 1000ms mark. – CommonsWare Sep 22 '16 at 13:31
1

I know this question is prehistoric, but it seems like people like me still happen to land on this question. So I guess it may make sense to add an answer I found in the documentation, which states:

To save persistent data, such as user preferences or data for a database, you should take appropriate opportunities when your activity is in the foreground. If no such opportunity arises, you should save such data during the onStop() method.

source

But wait, there's more:

Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may be killed by the system at any time without another line of its code being executed. Because of this, you should use the onPause() method to write any persistent data (such as user edits) to storage.

source

So wrapping up, it seems like persisting data onPause() is the best thing to do.

Peter
  • 340
  • 4
  • 13
  • +1 , Read a bit further and you will find "...these semantics will change slightly between applications targeting platforms starting...with Honeycomb, an application is not in the killable state until its onStop has returned". However, I agree with you to save in onPause(). The reason I save during onPause() has to do with the sharing of persistent data between Activities. Persistent data will become out-of-sync if saved in onStop() because a 2nd Activity is started before the 1st Activity's onStop(). – Java42 Aug 21 '20 at 22:54