本篇文章主要说一下项目结束时简单的内存泄漏检查与处理。
什么是内存泄漏?
内存泄漏(memory leak):是指应用在申请资源(内存)后,资源(内存)没有得到及时的释放。
区别:
内存溢出(out of memory): 是指应用在申请内存是,没有足够的内存供其使用,出现了out of memory。
内存泄漏的危害:
大量的内存泄漏最终会导致内存溢出(OOM)。
常见的导致内存泄漏的现象:
一、Handler引起的内存泄漏。
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mTextView.setText("星期四");
}
}
很常见的一段代码,handler通知UI线程更新UI。
当Handler使用内部类(包括匿名类)来创建的时候,handler会隐式的持有一个外部类对象(通常是Activity)的引用,当耗时操作结束,页面关闭
,因为handler持有activity的引用,导致activity不能被正常GC正常回收,从而导致内存泄漏
解决办法
Activity销毁的时候调用handler的removeCallbacks()方法
二、单利模式引起的内存泄漏。
public static SingleInstance getInstance(Context context) {
if (instance == null) {
instance = new SingleInstance(context);
}
return instance;
}
单利模式只是这类原因的一种表现。不单是单利,凡是
长生命周期对象持有短生命周期对象,导致短生命周期对象不能回收。
的现象都会导致内存泄漏现象,
解决办法
使用Application中的Context。
三、非静态内部类创建静态实例引起的内存泄漏
public class TestActivity extends Activity {
private static Hello sHello = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (sHello == null)
sHello=new Hello();
}
class Hello{
}
}
非静态的内部类会自动持有外部类的引用。
而使用非静态的内部类创建了一个静态实例(sHello) ,sHello 的生命周期和应用的生命周期一样长,sHello 会一直持有activity的引用,使activity无法被回收,从而导致内存泄漏。
解决办法
将内部类(Hello)改为静态内部类,因为静态内部类不在持有外部类的引用
static class Hello{
}
四、非静态匿名内部类引起的内存泄漏
非静态匿名内部类,会自动持有外部类的引用
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
}
}, 1000 * 60);
上面写了一个延迟的消息,被延迟的消息会在消息队列中存在60秒,这个消息中包含了handler的引用,Handler是一个匿名内部类的实例,持有了外部类(Activity)的实例,此时关闭activity,activity无法被回收,导致内存泄漏。而new Runnable这里也是匿名内部类实现的,同样也会持有Activity的引用,也会阻止Activity被回收。
解决办法:
把匿名内部类设置为静态的,这样就不会自动持有外部类的引用,也就不会引起内存泄漏了。
private static final Runnable sRunnable = new Runnable() {
@Override
public void run(){
}
};
Handler会持有Activity的引用,使用弱引用保存Activity。
五、注册,绑定后没有解除注册,绑定。
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
还有广播等需要注册的都需要解除注册。
六、资源对象没有关闭、释放、复用起的内存泄漏
资源性对象比如(Cursor,File文件等)没有关闭,
图片处理时Bitmap.recycle(),
ListView复用
Activity引起的内存泄漏。
使用若引用来保存Activity
private WeakReference<Activity> activity= null;
public void setActivity(Activity activity) {
this.activity = new WeakReference<Activity>(activity);
}
public Activity getActivity() {
return activity.get();
}
网友评论