美文网首页
Android Handler引发的内存泄漏

Android Handler引发的内存泄漏

作者: Ggx的代码之旅 | 来源:发表于2016-09-06 16:25 被阅读433次

相信很多人都这样用过Handler:

Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        //更新UI
        //...
        super.handleMessage(msg);
    }
};
new Thread(new Runnable() {
    @Override
    public void run() {
        //耗时操作
        //...
        handler.sendEmptyMessage(0);
    }
}).start();

很常见的一段段码,对没错,但是确实发生了内存泄漏。假如当在处理耗时操作的时候,可能是某段网络请求,也有可能是很复杂的计算,这时用户等的不耐烦了退出当前界面,由于异步操作,此时虽然界面销毁了,但是任务还在继续,由于线程中,引用这当前Activity中的对象handler,而handler对象又隐式的应用了当前的Activity,因此虽然界面销毁了,但是Activity并不会被回收。当任务执行完后,调用了handler方法,方法中又调用了更新界面,就会出现空指针异常崩溃。这算是最好的情况了,更严重的是由于Activity无法被销毁,那么就是占着那个地方不做事,这就是所谓的站着茅坑不拉屎。那么这块资源便浪费了,当用户来回反复切换的时候,资源占用越来越大,最终就算不空指针异常 也会出现OOM,这是由于内存泄漏导致的。

内存泄露的危害
只有一个,那就是虚拟机占用内存过高,导致OOM(内存溢出),程序出错。对于Android应用来说,就是你的用户打开一个Activity,使用完之后关闭它,内存泄露;又打开,又关闭,又泄露;几次之后,程序占用内存超过系统限制。

解决方案

  1. 在关闭Activity的时候停掉你的后台线程任务。线程停掉了,就相当于切断了Handler和外部连接的线,Activity自然会在合适的时候被回收。
  2. 如果你的Handler是被delay的Message持有了引用,那么使用相应的Handler的removeCallbacks()方法,把消息对象从消息队列移除就行了。
  3. 我们换一种写法,将handler对象声明成静态内部类,静态类不持有外部类的对象,所以你的Activity可以随意被回收。
private TestHandler testHandler=new TestHandler();
static class TestHandler extends Handler{
    @Override
    public void handleMessage(Message msg) {
        //更新界面操作
        //...
        super.handleMessage(msg);
    }
}

很快你会发现编译无法通过。因为上面说过了。静态类是不持有外部类的对象的,因此如果你在里面写了更新界面的操作当然会编译无法通过。解决办法当然有,就在静态类中在增加一个外部类的弱引用。

static class MyHandler extends Handler{
    private WeakReference<SearchContantActivity> mContext;
    public MyHandler(SearchContantActivity activity){
        mContext=new WeakReference<>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
        if(msg.what==0){
            SearchContantActivity activity=mContext.get();
            if(activity!=null){
                activity.xxx
            }
        }
        super.handleMessage(msg);
    }
}

但是这种仍然会出现异常,当你的界面退出后,界面的控件都会被销毁了,此时异步任务执行完,触发了handler发送消息,这时handler仍然会受到,从弱引用中拿到的Activity还是存在的,这时候你在去更新界面,那么理所当然就发生了NullPointException.所以最好的办法就是界面在正常发送handler,界面销毁就不发送handler,彻底切断它与Activity的联系,那么就一劳永逸了。

相关文章

  • (转载自diycode)2017 Android 面试题分享整理

    Android(安卓) Android基础知识 Android内存泄漏总结 Handler内存泄漏分析及解决 An...

  • Android 基础

    1、Android布局 2、Android内存泄漏总结 3 、Handler内存泄漏分析及解决 4...

  • 性能优化与保活

    ------内存泄漏优化------Android 内存优化你的 Handler 内存泄露 了吗?Android卡...

  • android学习资料

    第一部分: Android(安卓) Android基础知识 Android内存泄漏总结 Handler内存泄漏分析...

  • Android学习之旅

    1.Android基础知识2.Android内存泄漏总结3.Handler内存泄漏分析及解决4.Android性能...

  • Android Handler引发的内存泄漏

    相信很多人都这样用过Handler: 很常见的一段段码,对没错,但是确实发生了内存泄漏。假如当在处理耗时操作的时候...

  • Android知识体系总结

    第一部分:Android(安卓)Android基础知识Android内存泄漏总结Handler内存泄漏分析及解决H...

  • Android 消息机制 你了解多少

    级别:★★☆☆☆标签:「Handler」「Android」「消息机制」「内存泄漏」作者: Zoyp晨[https:...

  • java基础

    Handler怎样防止内存泄漏 handler引起内存泄漏的原因:由于handler的写法问题,如果handler...

  • Android的垃圾回收与内存泄露

    标签(空格分隔): Android 内存泄漏的基本知识请见博客一如何高效使用handler避免内存泄漏请见博客二 ...

网友评论

      本文标题:Android Handler引发的内存泄漏

      本文链接:https://www.haomeiwen.com/subject/uqbdettx.html