应用内存优化之OnLowMemory&OnTrimMemory

1.应用内存onLowMemory& onTrimMemory优化

onLowMemory& onTrimMemory简介:
OnLowMemory是Android提供的API,所有后台程序(优先级为background的进程,不是指后台运行的进程)都被杀死时,在系统内存还不足时,系统会调用OnLowMemory。
OnTrimMemory是Android 4.0之后提供的API,系统会根据不同的内存状态来回调。根据不同的内存状态,来响应不同的内存释放策略。


1.1 onLowMemory& onTrimMemory优化,需要释放什么资源?


在内存紧张的时候,会回调OnLowMemory/OnTrimMemory,需要在回调方法中编写释放资源的代码。
可以在资源紧张的时候,释放UI 使用的资源资:Bitmap、数组、控件资源。

1.2 OnLowMemory


OnLowMemory是Android提供的API,在系统内存不足,所有后台程序(优先级为background的进程,不是指后台运行的进程)都被杀死时,系统会调用OnLowMemory。系统提供的回调有:
Application.onLowMemory()
Activity.OnLowMemory()
Fragement.OnLowMemory()
Service.OnLowMemory()
ContentProvider.OnLowMemory()
除了上述系统提供的API,还可以自己实现ComponentCallbacks,通过API注册,这样也能得到OnLowMemory回调。例如:
public static class MyCallback implements ComponentCallbacks {
@Override
public void onConfigurationChanged(Configuration arg) {
}

@Override
public void onLowMemory() {
//do release operation
}
}
然后,通过Context.registerComponentCallbacks ()在合适的时候注册回调就可以了。通过这种自定义的方法,可以在很多地方注册回调,而不需要局限于系统提供的组件。
onLowMemory 当后台程序已经终止资源还匮乏时会调用这个方法。好的应用程序一般会在这个方法里面释放一些不必要的资源来应付当后台程序已经终止,前台应用程序内存还不够时的情况。


1.3 OnTrimMemory


OnTrimMemory是Android 4.0之后提供的API,系统会根据不同的内存状态来回调。系统提供的回调有:
Application.onTrimMemory()
Activity.onTrimMemory()
Fragement.OnTrimMemory()
Service.onTrimMemory()
ContentProvider.OnTrimMemory()
OnTrimMemory的参数是一个int数值,代表不同的内存状态:

TRIM_MEMORY_RUNNING_MODERATE
你的应用正在运行,并且不会被杀死,但设备已经处于低内存状态,并且开始杀死LRU缓存里的内存。
TRIM_MEMORY_RUNNING_LOW
你的应用正在运行,并且不会被杀死,但设备处于内存更低的状态,所以你应该释放无用资源以提高系统性能(直接影响app性能)
TRIM_MEMORY_RUNNING_CRITICAL
你的应用还在运行,但系统已经杀死了LRU缓存里的大多数进程,所以你应该在此时释放所有非关键的资源。如果系统无法回收足够的内存,它会清理掉所有LRU缓存,并且开始杀死之前优先保持的进程,像那些运行着service的。同时,当你的app进程当前被缓存,你可能会从onTrimMemory()收到下面的几种level.
TRIM_MEMORY_UI_HIDDEN

内存不足,并且该进程的UI已经不可见了。

TRIM_MEMORY_BACKGROUND
系统运行在低内存状态,并且你的进程已经接近LRU列表的,虽然你的app进程还没有很高的被杀死风险,系统可能已经清理LRU里的进程,你应该释放那些容易被恢复的资源,如此可以让你的进程留在缓存里,并且当用户回到app时快速恢复.
TRIM_MEMORY_MODERATE
系统运行在低内存状态,你的进程在LRU列表中间附近。如果系统变得内存紧张,可能会导致你的进程被杀死。
TRIM_MEMORY_COMPLETE
系统运行在低内存状态,如果系统没有恢复内存,你的进程是首先被杀死的进程之一。你应该释放所有不重要的资源来恢复你的app状态。
因为onTrimMemory()是在API 14里添加的,你可以在老版本里使用onLowMemory()回调,大致跟TRIM_MEMORY_COMPLETE事件相同。

提示:当系统开始杀死LRU缓存里的进程时,尽管它主要从下往上工作,它同时也考虑了哪些进程消耗更多的内存,如果杀死它们,系统会得到更多的可用内存。所以,在LRU整个列表中,你消耗越少的内存,留在列表里的机会就更大。 

以下4个是4.0增加紧急程度有高到低
TRIM_MEMORY_COMPLETE:内存不足,并且该进程在后台进程列表最后一个,马上就要被清理
TRIM_MEMORY_MODERATE:内存不足,并且该进程在后台进程列表的中部。
TRIM_MEMORY_BACKGROUND:内存不足,并且该进程是后台进程。
TRIM_MEMORY_UI_HIDDEN:内存不足,并且该进程的UI已经不可见了。

以下3个是4.1增加紧急有高到低
TRIM_MEMORY_RUNNING_CRITICAL:内存不足(后台进程不足3个),应用处于运行状态但是系统已经把大多数缓存应用杀掉了, 你必须释放掉不是非常关键的资源, 如果系统不能回收足够的运行内存, 系统会清除所有缓存应用并且会把正在活动的应用杀掉.
TRIM_MEMORY_RUNNING_LOW:内存不足(后台进程不足5个),应用处于运行状态并且不会被杀掉, 设备可以使用的内存非常低, 可以把不用的资源释放一些提高性能(会直接影响程序的性能)
TRIM_MEMORY_RUNNING_MODERATE:内存不足(后台进程超过5个),应用处于运行状态并且不会被杀掉, 设备使用的内存比较低, 系统会杀掉一些其它的缓存应用

系统也提供了一个ComponentCallbacks2,通过Context.registerComponentCallbacks()注册后,就会被系统回调到。

1.4 OnLowMemory和OnTrimMemory的比较

1,OnLowMemory 已经没有后台进程,系统内存还低,会被回调;而onTrimMemory被回调时,还有后台进程。
2,OnLowMemory是在最后一个后台进程被杀时调用,一般情况是low memory killer 杀进程后触发;而OnTrimMemory的触发更频繁,每次计算进程优先级时,只要满足条件,都会触发。
3,通过一键清理后,OnLowMemory不会被触发,而OnTrimMemory会被触发一次。

使用举例:

复制代码
1 @Override
2 public void onTrimMemory(int level) {
3 Log.e(TAG, " onTrimMemory ... level:" + level); 
6 }
7 
8 @Override
9 public void onLowMemory() { 
11 Log.e(TAG, " onLowMemory ... "); 
13 }
复制代码

2.系统回调优化
2.1 回调原理:
在Application、 Activity、Fragement、Service、ContentProvider中都可以重写回调方法,对OnLowMemory/OnTrimMemory进行回调,在回调方法中实现资源释放的实现。
以Activity为例,在Activity源码中能够看到对于onTrimMemory的定义,因此在回调的时候重写方法即可。

public void onTrimMemory(int level) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onTrimMemory " + this + ": " + level);
mCalled = true;
mFragments.dispatchTrimMemory(level);
}

2.2 释放资源:
在onTrimMemory释放资源,释放图片、数组、缓存等资源。

复制代码
@Override
public void onTrimMemory(int level) {
// TODO Auto-generated method stub
DLog.d(" onTrimMemory ... level:" + level);

switch(level)

{
case TRIM_MEMORY_UI_HIDDEN: 
//释放资源
/*编写释放资源代码*/
}

break;
}
super.onTrimMemory(level);
}
复制代码

下面是释放Bitmap的示例代码片段:

复制代码
// 先判断是否已经回收
if(bitmap != null && !bitmap.isRecycled()){ 
// 回收并且置为null
bitmap.recycle(); 
bitmap = null; 
} 
System.gc();
复制代码

list占用方法:
list.clear();然后在置空。

3.实现ComponentCallbacks


OnLowMemory除了上述系统提供的API,还可以自己实现ComponentCallbacks,通过API注册,这样也能得到OnLowMemory回调。例如:

复制代码
public static class ViewComponentCallbacks implements ComponentCallbacks {
@Override
public void onConfigurationChanged(Configuration arg) {
}

@Override
public void onLowMemory() {
//do release operation
}
}
复制代码

注册自定义的回调类:

ViewComponentCallbacks callBacks =new ViewComponentCallbacks();
this.registerComponentCallbacks( callBacks );

回调之后,即可进行重写:

@Override
public void onLowMemory() {
// TODO Auto-generated method stub
//释放资源的方法
super.onLowMemory();
}

猜你喜欢

转载自wenzongliang.iteye.com/blog/2184870
今日推荐