Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: saving application state when going to the "background"

I have a complex Android app with a decent amount of application state that needs to be persisted (in a specific format). Writing out the data is not an instantaneous operation and so it would be ideal to minimize persisting it unnecessarily.

Because of the persistence overhead it is not practical to persist the state every time it is changed. Ideally, persisting state would be triggered when the app is "backgrounded" by the user tapping the 'home' button or tapping the 'back' button on the app's root Activity (or by an incoming call, etc.). This minimizes persistence overhead while maintaining state consistency from the user's perspective. The question is how can you detect if the app is being "backgrounded"?

The Activity lifecycle calls (onStart, onResume, onPause and friends) don't help as the app has many different activities, any one of which could be active when the user taps 'home'. Furthermore, the calls get called when Activities get pushed, popped (and bottom killed) on the Activity stack and so they don't reflect if the app is going away or not.

So how does an app detect when it is going to the background?

like image 317
acoward Avatar asked Jan 22 '11 00:01

acoward


2 Answers

If you want to persist some state when any of your activities goes to the background you could always extend Activity, add two abstact methods which you call in onPause and onResume. Then each one of your Activities which extends this new abstract class would be forced to define saveState() and loadState(). These methods could define what to save and load for each activity.

That is just an example of using inheritance to force your programmers to implement otherwise overlooked methods and techniques methods. You can just tell your programmers, if you ever need to save the state of an activity just extend this type of activity and then the IDE will put them on the path of your design.

package com.yourcompany.yourpackage;

import android.app.Activity;

public abstract class ActivitySaveState extends Activity{

    @Override
    protected void onPause() {
        super.onPause();
        saveState();
    }

    @Override
    protected void onResume() {
        super.onResume();
        loadState();
    }


    public abstract void loadState();
    public abstract void saveState();



}

Also you could instantiate some of the state saving mechanisms for them in the super class (i.e. web service endpoint, DAO or w/e your persistence unit maybe.

@Override
    protected void onResume() {
        super.onResume();
        saveState();

        CustomDataAccessObject dao = new CustomDataAccessObject("Activity3");

        loadState(dao );
    }


    public abstract void loadState(CustomDataAccessObject dao);
like image 96
Anthony Ruffino Avatar answered Nov 09 '22 21:11

Anthony Ruffino


As far as I got in Android there is no concept of application going to background as a whole. Your application is thought of in terms of a federation of activities/services/... working together. And potentially you could configure it so that it can start from different activities, in different processes, in different tasks, so it's (almost?) impossible to figure out when your application goes to background.

Apart from this, to your question:

MyXxxActivity.onPause is the last safe chance you have to trigger the saving of data that has to be persisted across different "runs" of your application. This is not transient application state, instead it's stuff that goes to DB/File System storage and that you want to retrieve again in the next run.

I assume the application state you mention falls into this category.

So your saving must be triggered from each activity's onPause. If there's any state shared across different activities (e.g. in the Application), it should be collected from each onPause. Or its saving should be triggered as well from each onPause.

If the saving operation takes time, you should not run it on the main (UI) thread. Instead you should hand it off to another thread. Again, assuming this is important state that you do want to be persisted, then it's best to hand this work to a Service (as opposed to an AsyncTask e.g.).

like image 2
superjos Avatar answered Nov 09 '22 21:11

superjos