Copyright Notice:
This account published articles are from the public account, Chengxiang Moying (cxmyDev), chengxiang Moying all rights reserved.
Shall not be reproduced without permission.
One, foreword
In Android, when a running App is moved to the background, Android moves it into Cached state to speed up the next startup. In fact, the App process is still alive, but whether the corresponding component exists is not certain. And since the App process is still alive, the next startup will be very fast, which is often referred to as hot startup.
However, these apps that exit to the background are not completely safe and will not be cleaned up. They may just hold no components and do not occupy CPU resources, but they will still occupy memory space. LowMemoryKiller’s strategy is that when the system thinks it is running low on memory, it cleans up some less priority processes by priority to free up some memory for newly launched programs.
Therefore, in order to make our App live as long as possible in the background, it is nothing more than to reduce the memory, so as to increase the priority, and realize the function that is not recycled by the system (this is a general optimization scheme, rather than a survival scheme). So, if we can figure out what state our App is in, we can free up some memory resources that we don’t need to hold at this point to achieve our goal.
At this point, the onTrimMemory() callback method is used.
What is onTrimMemory
1. Functions of onTrimMemory
As mentioned earlier, we can implement the onTrimMemory() method to achieve simple management of the current App’s in-memory priority.
The onTrimMemory() callback method is an API provided after Android Level 14 (Android 4.0). Its main function is to remind developers that when the system is running out of memory, they should release some non-important memory resources. To avoid being killed by Android system services.
It can be seen that onTrimMemory() is essentially an opportunity to inform App that it is in different stages of system memory reclamation. At these times, it should release its own memory reasonably to avoid being killed by the system directly, so as to ensure the speed when the user starts the App next time.
The full method signature for onTrimMemory() is as follows:
public void onTrimMemory(int level)Copy the code
As you can see, it actually has a level parameter that marks the current App level in memory, which means that the onTrimMemory() method may be called multiple times.
2. The meaning of parameters returned by onTrimMemory
Since the onTrimMemory() method passes a level parameter, let’s take a look at what the various level parameters mean.
- TRIM_MEMORY_UI_HIDDEN: All of the UI of an App is hidden, most commonly by swapping the App into the background with the home or back button.
- TRIM_MEMORY_RUNNING_MODERATE: Indicates that the App is running properly and will not be killed, but currently the phone memory is a bit low and the system may start killing processes according to the LRU List.
- TRIM_MEMORY_RUNNING_LOW: indicates that the App runs normally and will not be killed. But cell phone memory is already very low.
- TRIM_MEMORY_RUNNING_CRITICAL: Indicates that the App is running properly, but the system has started to kill some cached processes according to the LRU List cache rules. At this point, you should try to free up memory resources that are not needed, otherwise the system may continue to kill other cached processes.
- TRIM_MEMORY_BACKGROUND: Indicates that the App has exited the background and is already at the lower end of the LRU List. There are other App processes in front of it, so you don’t need to worry about being killed.
- TRIM_MENORY_MODERATE: Indicates that the App has exited to the background and is in the middle of the LRU List and is at risk of being killed if the phone is still running low on memory.
- TRIM_MEMORY_COMPLETE: Indicates that the App exits the background and is at the top of the LRU List, and the memory of the phone is extremely low and may be killed by the system at any time.
In fact, the name of the level value can be roughly divided into three categories:
- UI in the background: TRIM_MEMORY_UI_HIDDEN.
- The state of the App when it is running in the foreground: TRIM_MEMORY_RUNNING_Xxx
- App is put in the background, callback in Cached state: TRIM_MEMORY_Xxx
Of these three, we usually only care if the App is Cached, because the system will not kill an App running in the foreground (it will trigger OOM), but if the App has some background services running, the service will be killed.
In Cached state, when you receive the TRIM_MEMORY_Xxx callback, note that this is only the location of the current App in the LRU List. In other words, if you recycle the top App process and still fail to meet your memory usage requirements, Processes may be further killed, that is, in extreme cases, it may be instantaneous to go from TRIM_MEMORY_BACKGROUND to TRIM_MEMORY_COMPLETE, so we need to be careful with them and try to judge all three states. Then do a unified memory resource reclamation process.
3. Which components can listen on onTrimMemory
Speaking of onTrimMemory() callbacks, it looks like it’s App specific, so at least in Application, it should be possible to override it to listen for callbacks. But in addition to Application, other components can also listen on it.
The components that can listen on onTrimMemory are:
- Application
- Activity
- Fragment
- Service
- ContentProvider
4. Customize onTrimMemroy listener
In addition to the components mentioned earlier that the system can listen on onTrimMemory() by default, we can also customize onTrimMemory listening.
Custom is also very simple, only need to implement ComponentCallbacks2 interface, then calls the Application. The registerComponentCallbacks sign up () method.
In addition to registerComponentCallbacks () method to register to monitor, if you don’t use the word, you can also use unregisterComponentCallbacks () solution.
So how does that work here? Let’s take a look at the source code for the Application.
As you can see, it’s actually maintained through a list of mComponentCallbacks.
OnTrimMemory () gets all callbacks from mComponentCallbacks for message distribution.
In this way, custom listening on onTrimMemory() is implemented.
The onTrimMemory() method is also marked @callsuper, so it is strictly required to override its subclass and call the onTrimMemory() method in the parent class, thus ensuring that message distribution is not missing.
5, onLowMemory ()
OnTrimMemory () is a new Api addition to Android 4.0, so for older devices you can listen for the onLowMemory() method, which is probably equivalent to the TRIM_MEMORY_COMPLETE callback.
The onLowMemory() method is also required for ComponentCallback, which inherits from The ComponentCallbacks2 interface.
3. Some thoughts on onTrimMemory?
1. Why onTrimMemory()
When the Android system is running low on memory, it cleans up some unimportant processes to free up memory resources for higher priority processes. This order, however, is mainly based on the priority of the LRU List, but it also considers which processes occupy the most memory, so that the system can release more memory more quickly.
Therefore, by keeping the App in the system as small as possible and occupying enough memory resources, the probability of being killed can be reduced, so that the hot startup mode can be adopted at the next startup to improve the user experience.
On the other hand, making App occupy less memory can also optimize the speed of the system. After all, the process of releasing memory of the system cleaning process also needs TO occupy CPU resources. In the big picture, it also makes sense.
Therefore, it is particularly important to optimize the release of the current App’s memory during onTrimMemory().
2. What resources should be released in the onTrimMemory callback
In the onTrimMemory() callback, there are several states in which non-important memory resources should be cleaned up. Without considering memory leaks, we actively cache some resources so that we can quickly access them during use, and this part of resources is the focus of our cleaning.
For these caches, as long as read into memory, such as the most common image cache, file cache, etc. For image cache, the market, the picture of the conventional load library, in general are three levels of cache, so tight in the memory, we should first clean up this part of the image cache, after all the picture is for memory, and when I come back again, although the memory of resources by recycling, we can restore it from the disk or network.
In addition to the resource cache, there are also some page-related resources, which also occupy memory. Consider removing redundant activities from the Activity Task and keeping only the Root Activity.
The main idea is to free up memory resources that can be recovered and not so important according to the onTrimMemory() callback to improve system performance and ensure that the current App process is not so easy to be recycled by the system.