Android Handler机制的几个疑问点验证

前提场景:Activity中new一个Handler并重写handleMessage方法

public class SingleTopActivity extends Activity {
@SuppressLint("HandlerLeak")
Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        LogUtil.i("name ====== " + SingleTopActivity.this.getClass().getSimpleName());
    }
};

...

}

疑问点1、在Activity finish的时候执行handler = null 是否真正销毁了Handler?

答:并不会,这个取决于通过handler发送的消息是否都处理完成,因为message 的target字段就是指向了当前的Handler,就是说每一个message都持有了一份当前Handler的引用,所以执行handler = null,只是当前的引用变成了 null,在message中可能还有其他的应用,因此new Handler时 在堆中开辟的内存不会被系统回收。

验证现象:执行handler = null以后,之前发送的延时任务仍然会被执行,handleMessage方法仍然会被正常回调。

疑问点2、在前提场景中,handler默认持有了Activity的应用,有内存泄漏的风险,那在关闭页面时,主动执行Activity的 onDestroy方法能解决可能出现的内存泄漏问题吗?

答:不能解决问题,其实没有必要主动执行onDestroy方法 因为你执行了finish后 过一会系统就会自动执行onDestroy ,此时通过命令adb shell dumpsys activity | grep  com.xxx.xxx 查看Activity栈信息,发现activity也已经从栈中移除掉了,但是如果此时有未执行完的消息(引用关系:activity -- handler -- message),activity在堆中的”真身”还是存在的,并不会被系统回收。(引用位置在handler所在的栈的位置)

另:查看栈信息截图 图中不存在SingleTopActivity了

验证现象:执行handler = null以后,之前发送的延时任务仍然会被执行,LogUtil.i("name ====== " + SingleTopActivity.this.getClass().getSimpleName()); 打印信息正常显示,并不会报空指针。

验证现象2:当有未执行完成的message时,SingleTopActivity中的finalize方法没有被执行,message执行完后,过了一会执行了finalize方法(GC在回收一个对象前会执行此对象的finalize方法)

验证现象3:通过AS自带的Memory分析工程查看内存,发现内存一直在增长,SingleTopActivity在增加

从内存分析图的右下角 Allocation Call Stack 也能看到SingleTopActivity在栈中的被引用的位置 就在Handler里面

通过以上分析验证,我们就明白了为什么在Activity关闭时把handler置为null,然后主动执行onDestroy方法,并不能解决可能发生的内存泄漏问题。

推荐最佳解决方案:在Activity关闭时执行   handler.removeCallbacksAndMessages(null);  (静态+弱应用的方案 第一增加static对象,第二弱应用可能被回收影响业务,不推荐)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值