您的位置:首页 > 移动开发 > Android开发

Android Handler导致内存泄漏的解决方案

2016-12-30 11:39 483 查看
最近一段时间,一直在优化项目,遇到了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~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息