Home » Android » java – How does Android handle background threads when leaving an Activity?

java – How does Android handle background threads when leaving an Activity?

Posted by: admin April 23, 2020 Leave a comment

Questions:

I need my Android app to save it’s state to disk when its activity is put in the background or killed. It’s been suggested that I start a thread when onPause() is called and perform any expensive I/O procedures there (see Saving/loading document state quickly and robustly for image editor).

In what situations will the OS kill the thread and how commonly do these situations occur?

I assume it will be like how Activities are dealt with where the OS can arbitrary decide to kill the thread but will mostly only do this when resources are extremely limited. It would be nice to find some specific documentation of this though.

From playing around, with some test code, a background thread started in onPause() will run indefinitely in the background on my device (I tried loading lots of apps and couldn’t get it to be killed).

For my specific app, I’m writing a bitmap editor where I’m using the Command pattern and the Memento pattern to allow undo and redo of edits. I’d like the user to be able to undo/redo their edits even e.g. the user gets a phone call and the activity is killed when it is put in the background. The best solution I can think of is to use a background thread to constantly save my command and memento objects to disk during application use and to finish up saving any objects that are left in a background thread if onPause is called. In the worse case, if the thread is killed I’ll only lose some edits.

How to&Answers:

In what situations will the OS kill the thread and how commonly do these situations occur?

The OS will not kill the thread, unless it is killing the process — Android does not do anything with threads you create yourself. If you are the foreground process, you will not be killed. The odds of Android killing the process within a few seconds of you losing the foreground (after onPause()) are miniscule. The documentation on process lifetime — what there is of it — can be found here.

Answer:

Your thread may be killed at any time after the activity is destroyed, or it may never be killed. Depending upon such a thread is very bad form — you could end up with a half-completed operation, or with a thread that sticks around forever.

If you wish to perform a background operation that continues even when there is no foreground activity, you almost always want to run it inside a Service. On the other hand, the service is less likely to be killed, but there’s no guarantee unless you use “startForeground”. This will end up displaying a notification to the user that something is happening in the background, but as far as I know it’s the only way of running an asynchronous background thread that is guaranteed not to be killed.

Honestly, the right answer is to make sure that there is never any temporary process state that will take a long time to save. If you are having to write a large file to reflect a few user changes, consider maintaining a “transaction log” which you can use to create a restartable save operation. Given this, you can safely run your saves in a service and know that even if it gets killed, it will be automatically restarted when resources become available.

Answer:

Normally, saving your state in onPause is the right thing to do if it’s quick. I don’t think it’s clearly documented when a process is killed, but you sometimes see it in logcat when you run some demanding apps (say, after running Google Earth and Browser).

There’s also an option in the Android DevTools to automatically destroy activities as you navigate away from them, although that probably doesn’t extend to the process. (DevTools are on the emulator, and on some rooted phones).

I think your approach sound reasonable – use a low-priority thread to constantly update the save data, and give it normal priority in onPause, and set a flag in onPause that tells it to terminate after it finishes.

Obviously, you’ll need to make sure you don’t run into synchronization issues if you get to onResume immediately after onPause (i.e. while the thread is still busy saving).