最近一段时间,一直在优化项目,遇到了Handler导致的内存泄漏的问题,在解决之余,也发表一下自己的感想,希望对别人有点帮助。
在优化项目的时候,我发现很多人都喜欢用匿名内部类的方式创建一个Handler(当年我也这么写→_→)
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
比较便捷,但是由于Java的内部类和匿名类会默认持有外部类的引用,如果Handler在等待发送延时消息的时候,Activity被finish,在Message被处理之前,Activity是无法被GC回收的,这就导致了Activity的内存泄漏,而且在Activity被finish之后,绝大多数情况handleMessage已经没有执行的必要了,但是这种方法获取的Handler依然会把这个Message执行下去,做了一些无用的操作而且还容易抛出异常。
网上有用static来修饰Handler来解决匿名类引用外部类的问题,虽然能解决引用外部类的情况,但是却增加了项目初始化的时间成本和方法区的空间,我并不太喜欢这种方式,而是采取了另一种外部类+软引用的方式解决这个问题,代码如下:
CustomHandler
/**
* Description: TODO
* author: Wang
* date: 16/12/29 上午10:20
*
* Copyright©2016 by wang. All rights reserved.
*/
public class CustomHandler extends Handler {
private SoftReference<CustomHandleMessage> object;
public CustomHandler(@NonNull CustomHandleMessage onHandleMessage) {
object = new SoftReference(onHandleMessage);
}
@Override
public void handleMessage(Message msg) {
CustomHandleMessage onHandleMessage = object.get();
if (onHandleMessage != null) {
onHandleMessage.onHandler(msg);
}
}
/**
* 发送延时消息
*
* @param message
* @param delayed
*/
public void postDelayed(Message message, long delayed) {
CustomRunnable runnable = new CustomRunnable(this, message);
this.postDelayed(runnable, delayed);
}
}
CustomHandleMessage
/**
* Description: TODO
* author: Wang
* date: 16/12/29 下午10:10
*
* Copyright©2016 by wang. All rights reserved.
*/
public interface CustomHandleMessage {
void onHandler(Message msg);
}
CustomRunnable
/**
* Description: TODO
* author: Wang
* date: 16/12/29 下午10:08
*
* Copyright©2016 by wang. All rights reserved.
*/
public class CustomRunnable implements Runnable {
private CustomHandler handler;
private Message message;
public CustomRunnable(CustomHandler handler, Message message) {
this.handler = handler;
this.message = message;
}
@Override
public void run() {
handler.sendMessage(message);
}
}
每个想要使用CustomHandler的类都要实现CustomHandleMessage接口,例如:
/**
* Description: TODO
* author: Wang
* date: 11/28/16 11:08 AM
*
* Copyright©2016 by wang. All rights reserved.
*/
public class TestActivity extends BaseActivity implements CustomHandleMessage {
private CustomHandler handler = new CustomHandler(this);
@Override
public void onHandler(Message msg) {
LogUtil.i(TAG, "msg : " + msg.what);
}
/**省略的方法**/
}
这样写的好处是,避免了Handler对外部类的引用,不再影响GC对外部类的回收。
打完收工。
PS:本猿也是最近才开始涉及Android内存的优化,有不足或错误的地方还请大家多多指正。
如果有用,顺手点个赞吧 O(∩_∩)O~~