Search code examples
androidmemory-managementandroid-lifecycle

Does `onTrimMemory` get called on UI thread or not?


I want to implement onTrimMemory(int level) in an activity, to write some Bitmap objects in memory to the hard drive, and recycle them. But I am not sure if this will block the UI thread or not, should I run the code within another thread? Or maybe the method is already run on another thread by default?

Another relevant question is: does onTrimMemory get called when the activity is in the foreground? the doc says:

This will happen for example when it goes in the background and there is not enough memory to keep as many background processes running as desired.

In other words, if I implement onTrimMemory properly (releasing enough memory), do I need to worry about OOM errors?

Or onTrimMemory only get called when the activity enters background, so OOM can still happen when the app is in the foreground?


Solution

  • 1. Does onTrimMemory get called on UI thread?

    Yes. From the docs:

    ...methods that respond to system callbacks (such as onKeyDown() to report user actions or a lifecycle callback method) always run in the UI thread of the process.

    If you'd like assurance from the source code, note that the root of the call takes place here; a Runnable posted to the ActivityThread's main Handler.

    2. Does onTrimMemory get called when the activity is in the foreground?

    I am not sure. The docs do not explicitly forbid it, so a well-designed application should allow for this possibility.

    It looks like this call in the source code might potentially apply to a foreground app.

    3. If I implement onTrimMemory properly (releasing enough memory), do I need to worry about OOM errors?

    You always need to worry about OOM errors. It is always possible to request an allocation larger than the system can provide. The onTrimMemory() scheme reflects a way to free up resources on a "best effort" basis; there is no guarantee that your app, or the others on the system, will cooperate to reach any particular memory threshold.

    If your app is in the background, it might not be doing too much, particularly in the way of allocations. Maybe it is the other apps on your device getting OOMs that you should be worried about (if your app fails to release "enough" memory in response to an onTrimMemory() call).

    4. Or onTrimMemory only get called when the activity enters background, so OOM can still happen when the app is in the foreground?

    As mentioned, OOMs can happen any time you try to make an allocation. Hopefully the other apps on your device will make a good-faith effort to reduce their memory consumption (after on onTrimMemory()) so that the maximal amount of resources are available for your foreground app. If they don't, they are likely to be terminated (as you can see from the logic in ActivityManagerService.java), which frees up even more resources.

    The system will do its very best to make sure your foreground app has the resources it's requesting. That said, you should plan your memory usage in a sensible way, and be able to recover gracefully in the event of errors (OOMs).