Android性能优化之内存优化
内存泄漏出现的场景及解决办法
内存泄漏是指我们在向程序申请了内存存储对象后,当该对象不需要用了的时候又不把内存释放还给程序,从而引发内存溢出(out of memory),下面例举一下可能造成内存泄漏的一些场景。
- 静态集合
我们的静态集合中存储了对象,因为这些对象一直被集合持有,所以对象无法被回收,特别是集合中对象越来越多的时候越容易OOM。
- 示例:
static List<Object> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Object o = new Object();
list.add(o);
}
-
解决办法:
将list清空,并且置为null
list .clear();
list = null;
- static修饰的成员变量
static修饰的成员变量其实与上面的静态集合道理差不多,都是由于引用被静态持有,导致其生命周期与静态生命周期相等了
- 示例:
private static Context mContext;
private void get(Context context) {
this.mContext = context;
}
- 解决办法:
1. Context调用ApplicationContext
private static Context mContext;
private void get(Context context) {
this.mContext = context.getApplicationContext();
}
2. 使用弱引用关联,当内存不足时,gc会将弱引用给回收
private static WeakReference<Activity> mActivity;
private void get(Activity activity) {
this.mActivity = new WeakReference<Activity>(activity);
}
- 非静态内部类或匿名类
非静态内部类或匿名类都会隐性持有外部类引用
private static test t=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_doc_main);
if (t == null) {
t = new test();
}
}
private class test{
private void test(){
}
}
- 解决办法:
将非静态内部类转成静态内部类,这样就不会持有外部对象的引用了
-
资源对象使用后未关闭
我们平时在使用使用一些数据库,流,bitmap,广播等等时,我们都需要在不需要用的时候及时的关闭,不然对象就会一直占着内存,无法回收掉,记住一个点,有开就有关 -
Handler消息传递
关于handler消息传递引发的内存泄漏有两个地方,第一,非静态内部类,第二,Handler持有外部对象的引用
- 解决办法:
第一种
第一点:这一点我们上面说过了解决办法,将handler设置为静态内部类即可;
第二点:我们有时候可能需要从handler的构造中将上下文传递过去,这样就持有了外部对象的引用了,这时候我们可以用弱引用关联上下文,避免内存泄漏
第二种
在退出的时候将handler中的消息队列清空,结束handler生命周期
mHandler.removeCallbacksAndMessages(null);
- 内存泄漏的其他场景
我们常用的listview,使用用ViewHolder来复用对象,避免因为条目过多的时候因为重复的创建对象而造成大量的内存占用现象。
webview导致的内存泄漏,我们可以从清除绑定的服务,清除缓存,清除view,再退出这几个方面来进行
if( mWebView!=null) {
ViewParent parent = mWebView.getParent();
if (parent != null) {
((ViewGroup) parent).removeView(mWebView);
}
mWebView.stopLoading();
mWebView.getSettings().setJavaScriptEnabled(false);
mWebView.clearHistory();
mWebView.clearView();
mWebView.removeAllViews();
mWebView.destroy();
}
还有一些就是我们平时要注意context的使用了,要注意他的使用场景与生命周期
Bitmap优化
Android的bitmap优化可以从四个方面入手
- 及时释放资源
当我们使用完bitmap的时候及时释放资源,避免资源占用
- api10之前直接调用Bitmap.recycle()进行释放,
- api10之后采用软引用的方式
2.根据分辨率适配图片或者缩放裁剪图片 - 设置多套分辨率的图片,将其放在不同分辨率的文件夹中
- 缩放或者裁剪图片这个要根据需求来进行,如果需求允许的情况下可以采用这种方式BitmapFactory.decodeResource()
- 加载大图的时候我们可以采用inJustDecodeBounds / inSmapleSize来实现;参考链接浅谈BitmapFactory.Options
3.根据需求来设置图片编码 - bitmap有四种解码方式,ALPHA_8,RGB_565,ARGB-4444,ARGB_8888(默认)位数越高,越清晰,我们可以根据实际需求来对bitmap用inperferredConfig设置编码方式
4.设置图片三级缓存 - 给bitmap设置三级缓存,内存-本地-网络