美文网首页Android开发
Android--Handler的内存泄漏原因及解决方法

Android--Handler的内存泄漏原因及解决方法

作者: chaoyu168 | 来源:发表于2018-01-25 17:24 被阅读0次

    一、如何造成内存泄漏:

    1、主线程的Looper对象会伴随该应用程序的整个生命周期

    2、Java里,非静态内部类和匿名类都会潜在引用它们所属的外部类

    发送的延迟空消息(EmptyMessageDelayed)后、消息处理被前,该消息会一直保存在主线程的消息队列里持续时间,在持续时间里,该消息内部持有对handler的引用,由于handler属于非静态内部类,所以又持有对其外部类(即MainActivity实例)的潜在引用,引用关系如下图

    这条引用关系会一直保持直到消息得到处理,从而,这阻止了MainActivity被垃圾回收器(GC)回收,同时造成应用程序的内存泄漏,如下图:

    二、解决方法

    1、使用静态内部类+弱引用

    在Java里,非静态内部类匿名类都会潜在的引用它们所属的外部类。 但是,静态内部类不会。所以,避免内存泄漏的解决方案是:只需要将Handler的子类设置成静态内部类;同时,还可以加上 使用WeakReference弱引用持有Activity实例。

    原因:弱引用的对象拥有短暂的生命周期。在垃圾回收器线程扫描时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。

    [java] view plain copy print?

    public class MainActivity extends AppCompatActivity {  

    //将Handler改成静态内部类  

    private static class FHandler extends Handler{  

    //定义弱引用实例  

    private WeakReference reference;   

    //在构造方法中传入需要持有的Activity实例  

    public MyHandler(Activity activity) {   

    reference =new WeakReference(activity); }  

    //通过复写handlerMessage()从而决定如何进行更新UI操作  

    @Override  

    public void handleMessage(Message msg) {  

    //省略代码  

                }  

    }  

    @Override  

    protected void onCreate(Bundle savedInstanceState) {  

    //主线程创建时便自动创建Looper和对应的MessageQueue,之前执行Loop()进入消息循环  

    super.onCreate(savedInstanceState);  

            setContentView(R.layout.activity_main);  

    //实例化Handler的子类  

    //这里并无指定Looper,即自动绑定当前线程(主线程)的Looper和MessageQueue  

    private final Handler showhandler = new FHandler();  

    //启动子线程  

    new Thread(){  

    @Override  

    public void run() {  

    super.run();  

    try {  

    Thread.sleep(10000);  

    }catch (InterruptedException e) {  

                        e.printStackTrace();  

    showhandler.sendEmptyMessageDelayed(0x1,10000);  

                    }  

                }  

            }.start();  

        }  

    2、当外部类结束生命周期时清空消息队列

    内存泄漏的原因是: 当Activity结束生命周期时,Handler里的Message可能还没处理完,从而导致一系列的引用关系。其实,我们只要在当Activity结束生命周期时清除掉消息队列(MessageQueue)里的所有Message,那么这一系列引用关系就不会存在,就能防止内存泄漏。

    解决方案:当Activity结束生命周期时(调用onDestroy()方法),同时清除消息队列里的所有回调消息(调用removeCallbacksAndMessages(null))。

    [java] view plain copy print?

    @Override  

    protected void onDestroy() {  

    super.onDestroy();  

    mHandler.removeCallbacksAndMessages(null);  

        }  

    相关文章

      网友评论

        本文标题:Android--Handler的内存泄漏原因及解决方法

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