相关参考链接:
前言
在一台Andriod设备上会同时运行多个应用,每个应用都在申请内存,而内存的容量是有限的,一个应用占据过多的内存会导致其他应用就分配的少,且应用占据过多内存,当其处于后台时,更容易被加入清理队列。因此,每个应用都应该做好内存优化,在内存不足时释放一些不需要的资源,在内存严重不足时释放一些非关键性的资源。
一、 OnLowMemory
OnLowMemory是Android提供的API,在系统内存不足,所有后台程序(优先级为background的进程,不是指后台运行的进程)都被杀死时,系统会调用OnLowMemory。
系统为其提供回调的组件有:Application/Activity/Fragementice/Service/ContentProvider,在这些组件中实现了该接口
除了上述系统提供的API,还可以自己实现ComponentCallbacks,通过API注册,这样也能得到OnLowMemory回调。
public static class MyCallback implements ComponentCallbacks{
@Override
public void onConfigurationChanged(Configuration arg){
}
@Override
public void onLowMemory(){
//do release operation
}
}
复制代码
然后通过
registerComponentCallbacks(new MyCallback())//该方法实现注册
复制代码
在合适的时候注册回调就可以了。通过这种自定义的方法,可以在很多地方注册回调,而不需要局限于系统提供的组件。
二、OnTrimMemory
OnTrimMemory是Android 4.0之后提供的API,系统会根据不同的内存状态来回调。系统提供的回调有:Application/Activity/Fragement/Service/ContentProvider
OnTrimMemory 的参数是一个int数值,代表不同的内存状态:
UI不可见
释放内存的迫切性由高到底
TRIM_MEMORY_COMPLETE:内存不足,并且该进程在后台进程列表最后一个,如果没有内存,马上会被释放
TRIM_MEMORY_MODERATE:内存不足,并且该进程在后台进程列表的中部,释放内存可以帮助位于列表后部的进程保活。
TRIM_MEMORY_BACKGROUND:内存不足,并且该进程已变成后台进程,在后台进程列表中。
UI隐藏
TRIM_MEMORY_UI_HIDDEN:应用程序的所有UI都被隐藏了,此时可以释放一些UI资源。
UI可见下
释放内存的迫切性由高到底
TRIM_MEMORY_RUNNING_CRITICAL:内存严重不足,此时应该释放一些非关键性资源,否则会导致其他后台进程被杀死
TRIM_MEMORY_RUNNING_LOW:内存不足,此时应该释放一些不需要的资源
TRIM_MEMORY_RUNNING_MODERATE:内存不太充足,此时应该释放一些不需要的资源
对于OnTrimMemory,系统也提供了一个ComponentCallbacks2,可以在非系统组件里收到回调,如下(其实ComponentCallbacks2继承了ComponentCallbacks):
public static class MyCallback implements ComponentCallbacks2{
@Override
public void onTrimMemory(int level){
}
@Override
public void onConfigurationChanged(Configuration newConfig){
}
@Override
public void onLowMemory(){
}
}
//回调代码相同
Context.registerComponentCallbacks()
复制代码
三、 OnLowMemory和OnTrimMemory的比较
OnLowMemory 被回调时,该进程处于后台进程且即将被杀死,相当于 OnTrimMemory的TRIM_MEMORY_COMPLETE状态
OnLowMemory是在本应用最后一个后台进程被杀前被调用;而OnTrimMemory的触发更频繁,每次计算进程优先级时,只要满足条件,都会触发。
OnLowMemory只是为了 API14之前的系统进行内存优化,而在API14之后应该尽量使用OnTrimMemory
四、总结
为什么需要 onTrimMemory()
如果在每个系统组件中都重载OnLowMemory和OnTrimMemory方法,这样会导致繁琐,大多数开发者也不愿意这么做,但是对于一些大量占用资源的组件,我们在使用的时候应该重载这两个方法,在内存不足的情况下,释放掉这些非关键性的资源,防止影响其他进程的使用同时也能让自己的进程存活更久。
2. 在 onTrimMemory 回调中,应该释放哪些资源
在 onTrimMemory() 回调中,应该在一些状态下清理掉不重要的内存资源。在不考虑内存泄露的情况下,有一些资源是我们主动缓存起来,以便我们在使用的过程中可以快速获取,而这部分资源就是我们清理的重点。
对于这些缓存,只要是读进内存内的都算,例如最常见的图片缓存、文件缓存等。拿图片缓存来说,市场上,常规的图片加载库,一般而言都是三级缓存,所以在内存吃紧的时候,我们就应该优先清理掉这部分图片缓存,毕竟图片是吃内存大户,而且再次回来的时候,虽然内存中的资源被回收掉了,我们依然可以从磁盘或者网络上恢复它。
除了资源缓存之外,还有一些页面相关的资源,也是占据内存的,可以考虑清理掉 Activity Task 中,多余的 Activity,只保留 Root Activity 。
其实核心思想,就是根据 onTrimMemory() 回调的一些信息,来释放我们持有的可被恢复,不那么重要的内存资源,以提高系统性能,已经保证当前 App 的进程不那么容易被系统回收。