一.Handler使用不当造成的内存泄漏
内存泄漏危害极其严重,会造成OOM,使应用闪退。一般不容易发现,需要借助RefWatcher工具来进行检测。至于RefWatcher的使用方法,在这里本文就不再进行阐述,需要了解的朋友请自行在网上查询相关资料。
1.handler延时发送消息(sendEmptyMessageDelayed、sendMessageDelayed等方法)可能会造成内存泄漏
一般我们使用handler延时发送消息可能会这样用:
private android.os.Handler handler = new android.os.Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//...
//处理消息
//...
}
};
//发送消息
handler.sendMessageDelayed(Message.obtain(),100000);
咋看之下好像没有什么问题,但是如果我们在发送了消息后,马上把当前Activity关闭(调用finish()方法)。这样Activity应该会被系统回收,但是我们的消息已经发送到消息处理队列中,并且延时10秒处理,也就是说系统回收Activity时消息还没有处理完毕。所以当Activity要被回收时,由于handler持有Activity的引用,Activity而不能被系统回收,造成内存泄漏,如下图所示。
解决办法:
(1). 当Activity销毁时把发送的消息从消息队列中移除就可以解决内存泄漏问题,即在Activity的onDestroy方法中添加handler.removeCallbacksAndMessages(null)方法即可。
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
}
(2). 将Handler声明为静态类。
private static class RefWatcherHandler extends android.os.Handler {
private final WeakReference<Activity> mActivityReference;
public RefWatcherHandler(Activity activity) {
this.mActivityReference = new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
final Activity activity = mActivityReference.get();
if (activity != null) {
//...
//处理消息
//...
} else {
removeCallbacksAndMessages(null);
}
}
}
//使用
private RefWatcherHandler refWatcherHandler = new RefWatcherHandler(this);
//发送消息
refWatcherHandler .sendMessageDelayed(Message.obtain(),100000);
2.handler.postDelayed可能会造成内存泄漏
使用handler.postDelayed是一般是这样用:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//...
}
}, 100000);
如果在postDelayed之后立即关闭Activity也会造成内存泄漏,原因和上面的一样。
解决办法:
当Activity销毁时把post的Runnable移除,如下:
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(runnable);
}
二.Thread使用不当造成的内存泄漏
一般我们使用Thread来执行一些后台耗时的任务,如下:
new Thread() {
@Override
public void run() {
super.run();
try {
Thread.sleep(10000); //模拟耗时任务
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, "thread");
}
}.start();
如果耗时任务还没有执行完毕就把当前Activity关闭,就会造成内存泄漏。原因也大同小异。
解决方法:
在Activity销毁时,把线程停止即可。如下:
@Override
protected void onDestroy() {
super.onDestroy();
thread.interrupt();
}
至此完毕,如有错误,敬请指教。