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

一、如何造成内存泄漏:

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的内存泄漏原因及解决方法)