Search code examples
androidandroid-studioandroid-serviceandroid-sharedpreferencesandroid-ondestroy

SharedPreferences not saved in onDestroy of Service


Before the activity get's killed (when OnDestroy is called), I am saving some int values in SharedPreferences.

But what I have noticed is that it takes about a second for the values to be saved but the app doesn't wait for that before destroying the Activity.

Can I do some kind of Wait before it gets killed?

Here's my example:

@Override
public void onDestroy(){

    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putInt("finalXPos", finalX);
    editor.putInt("finalYPos", finalY);
    editor.commit();

    super.onDestroy();
    removeView();
}

======================>> EDIT <<======================

I made a mistake and said this was for an Activity but it's not. I am calling the onDestroy of a Service and unfortunately there is no onPause method to override there...


Solution

  • As per the docs, don't rely on the onDestroy() method to persist your data. Use onPause() instead.

    Note: do not count on this method being called as a place for saving data!

    For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running.

    There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.

    Also, you could try to use the method apply() instead of commit() on your SharedPreferences.Editor because it saves your data faster, asynchronously, and there's no return value to handle at all.


    EDIT: Ok, so you're using a Service. Problem is, their lifetime can outlast an Activity life by far, as they keep running in the background. So the onDestroy() of your service can take a very long time before it gets called, even if you close your app with the back button.

    I'm not sure how your app is supposed to work, but I can suggest a few things.

    1. If you want to work on your SharedPreferences when the user closes the app, move that method to an Activity or;
    2. Inside the Activity#onPause() you can destroy the Service using the stopService() method. (See example below).
    3. If your Service is supposed to do some work and if after this work is done it should modify the SharedPreferences, you could try to use an IntentService, because once this kind of Service finishes its job, it'll destroy itself. But take note, only one IntentService can run at a time! It runs on a FIFO queue.
    4. If you don't want to use an IntentService, you could also call stopSelf() from within your regular Service to stop it and destroy it.

    Example on finishing a Service:

    @Override
    protected void onPause() {
        super.onPause();
        stopService(new Intent(context, YourService.class));
    }
    

    More info about IntentService on this tutorial. More info on a Service lifecycle on this link.