资讯专栏INFORMATION COLUMN

每日一道面试题(第1期)---自定义handler如何有效保证内存泄漏问题

番茄西红柿 / 2150人阅读

摘要:但是如果你直接创建一个对象,然后重写内部方法,那么一定会提醒你会有内存泄漏的可能。所以当的生命周期结束后,而中还存在未处理的消息,那么上面一连串的引用关系就不允许的对象被回收,就造成了内存泄漏。

零零碎碎的东西总是记不长久,仅仅学习别人的文章也只是他人咀嚼后留下的残渣。无意中发现了这个每日一道面试题,想了想如果只是简单地去思考,那么不仅会收效甚微,甚至难一点的题目自己可能都懒得去想,坚持不下来。所以不如把每一次的思考、理解以及别人的见解记录下来。不仅加深自己的理解,更要激励自己坚持下去。

handler作用

SDK文档是这么说的。

There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

我们一般就是用来更新UI线程的。具体点就是在子线程进行耗时操作,比如获取网络图片,然后需要在主线程更新图片,就需要handler+Message+Loop+MessageQueue来帮忙啦。

但是如果你直接创建一个handler对象,然后重写内部handlerMessage方法,那么AS一定会提醒你会有内存泄漏的可能。

为什么会造成内存泄漏

Android内存泄漏:需要被GC回收的对象因为被其他存活的对象所持有引用,而导致GC不能回收此对象。那么这块内存就会在程序运行期间长期被占据,造成系统内存的浪费,使系统运行缓慢甚至崩溃。

那么handler什么时候会造成内存泄漏呢?

发送延迟消息

众所周知,匿名内部类持有外部类的引用,那么handler对象就会持有activity对象的引用。handler发送message到MessageQueue,message持有handler的引用,而MessageQueue会持有message的引用,而MessageQueue是属于TLS(ThreadLocalStorage)线程,是与Activity不同的生命周期。

所以当Activity的生命周期结束后,而MessageQueue中还存在未处理的消息,那么上面一连串的引用关系就不允许Activity的对象被回收,就造成了内存泄漏。

解决办法

知道了内存泄漏是由引用链造成的,那么解决方法也就是破坏上面的引用链。

首先是引用的类型,有强引用、软引用、弱引用、虚引用,上面的引用链都是强引用。

所以第一种方法,自定义静态内部类,如果想使用外部类的方法,那就通过弱引用的方法引入Activity对象。

public class BaseActivity extends Activity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public void myHandleMessage(Message msg){}

    static class MyHandler extends Handler{
        WeakReference mActivityReference;
        public MyHandler(BaseActivity activity){
            mActivityReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            BaseActivity activity = mActivityReference.get();
            if(activity != null){
                activity.myHandleMessage(msg);
            }
        }
    }
}

你可以自定义在BaseActivity中,在其他Activity中创建Myahndler对象,通过重写myHandleMessage方法进行消息处理。

这种方法就是处理了Activity与Handler之间的引用,这种引用可以再GC时被回收。

第二种,就是处理后面的引用。既然是Activity要被回收时还有未被处理的消息,那么在Activity要被回收时清除消息就可以了。

@Override
    protected void onDestroy() {
        super.onDestroy();
        if(mHandler != null){
            mHandler.removeCallbacksAndMessages(null);
        }
    }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7034.html

相关文章

  • 每日一道面试)---一般什么情况下会导致内存泄漏

    摘要:显而易见的,当这个是的时,就不存在内存泄漏的问题。这个我在第一期自定义如何有效保证内存泄漏问题已经说得很明白了。 零零碎碎的东西总是记不长久,仅仅学习别人的文章也只是他人咀嚼后留下的残渣。无意中发现了这个每日一道面试题,想了想如果只是简单地去思考,那么不仅会收效甚微,甚至难一点的题目自己可能都懒得去想,坚持不下来。所以不如把每一次的思考、理解以及别人的见解记录下来。不仅加深自己的理解,更要激...

    番茄西红柿 评论0 收藏0
  • 金三银四,2019大厂Android高级工程师面试整理

    摘要:原文地址游客前言金三银四,很多同学心里大概都准备着年后找工作或者跳槽。最近有很多同学都在交流群里求大厂面试题。 最近整理了一波面试题,包括安卓JAVA方面的,目前大厂还是以安卓源码,算法,以及数据结构为主,有一些中小型公司也会问到混合开发的知识,至于我为什么倾向于混合开发,我的一句话就是走上编程之路,将来你要学不仅仅是这些,丰富自己方能与世接轨,做好全栈的装备。 原文地址:游客kutd...

    tracymac7 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<