关于HandlerLeak的一点理解

之前很多代码是这样写的:

	@SuppressLint("HandlerLeak")
	Handler handler = new Handler() {
		public void handleMessage(Message msg) {

			switch (msg.what) {
			case HyyConstants.REFRESH_LIST:
				Toast.makeText(
						HyyDLApplication.getContext().getApplicationContext(),
						"Refresh list", Toast.LENGTH_SHORT).show();
				initList();
				break;

			default:
				break;
			}

		};
	};
这样做有一个好处是可以在Handler里触发Activity的操作。但也造成了内存泄漏的隐患。隐患是这样形成的:

在应用程序线程的MessageQueue中排队的Message对象还保留他们的目标Handler。如果Handler是一个内部类(注:无论是匿名还是非匿名,匿名是比较常见用法),它的外部类将被保留(至于为什么,请参考Java嵌套类相关说明)。为了避免泄漏外部类,声明一个Handler子类为静态内部类(注:这样就避免了Handler对象对外部类实例的自动引用),其内部持有一个对外部类对象的WeakReference。

再分析一下这几个泄漏问题:(1)排队中的Message对象对Handler的持有导致泄漏;(2)Handler对象对外部类(如Activity或Service)实例的强引用持有。

方案:(1)针对第1个原因,在使用Handler的组件生命周期结束前清除掉MessageQueue中的发送给Handler的Message对象(例如在Activity或Service的onDestroy()中调用Handler的remove*方法);(2)针对第2个原因,Handler的实现类采用静态内部类的方式,避免对外部类的强引用,在其内部声明一个WeakReference引用到外部类的实例。


关于Handler的remove*方法,这儿介绍一下(可以参考源码或文档)

removeCallbacks(Runnable r) ——清除r匹配上的Message。

removeCallbacks(Runnable r, Object token) ——清除r匹配且匹配token(Message.obj)的Message,token为空时,只匹配r。

removeCallbacksAndMessages(Object token) ——清除token匹配上的Message。

removeMessages(int what) ——按what来匹配

removeMessages(int what, Object object) ——按what来匹配

我们更多需要的是清除以该Handler为target的所有Message(包括Callback),那么调用如下方法即可

    handler.removeCallbacksAndMessages(null);


最终代码像这个样子:

packageorg.dragonboy.example;
 
importjava.lang.ref.WeakReference;
 
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.Message;
 
/**
 * @author dragonboyorg@qq.com
 */
publicclass MyActivity extendsActivity {
    privateMyHandler mHandler;
 
    @Override
    protectedvoid onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        mHandler = newMyHandler(this);
    }
 
    @Override
    protectedvoid onDestroy() {
        // Remove all Runnable and Message.
        mHandler.removeCallbacksAndMessages(null);
 
        super.onDestroy();
    }
 
    staticclass MyHandler extendsHandler {
        // WeakReference to the outer class's instance.
        privateWeakReference<MyActivity> mOuter;
 
        publicMyHandler(MyActivity activity) {
            mOuter = newWeakReference<MyActivity>(activity);
        }
 
        @Override
        publicvoid handleMessage(Message msg) {
            MyActivity outer = mOuter.get();
            if(outer != null) {
                // Do something with outer as your wish.
            }
        }
    }
}





  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值