Android中Handler引起的内存泄露

                     Android常用编程中,Handler在进行异步操作并处理返回结果时,经常被使用。通常我们的代码会这样实现。

     

     public class  MainActivity extends Activity{

   

       private final Handler mHandler = new Handler(){

          

           @Override

            public void handleMessage(Message msg){

              //....

         }

     }       

}

   但是,上面的代码是可能导致内存泄露的,代码中哪里可能导致内存泄露呢。又是如何导致内存泄露的呢?我们接下来就慢慢分析下。


   1.当一个Android应用启动的时候,会自动创建一个供应用主线程使用的Looper实例。Looper的主要工作就是一个一个处理消息队列中的消息对象。在Android框架的事件(比如Activity的生命周期方法调用,和按钮点击等)都是放入到消息中)然后加入到Looper要处理的消息队列中,由Looper负责一条一条的进行处理。主线程中的Looper生命周期和当前应用一样长。

   2.当一个Handler在主线程进行初始化之后,我们发送了一个target为这个Handler的消息到Looper处理的消息队列时,实际上已经发送的消息已经包含了一盒Handler实例的引用,只有这样的Looper在处理到这条消息时,Handler调用handleMessage()Looper才会去处理Message。

   3.在java中,非静态的内部类和匿名内部类都会隐式的持有其外部类的引用。静态的内部类不会持有外部类的引用。(在内部类构造的时候,会将外部类的引用传递进来,并且作为内部类的一个属性,所以内部类会持有一个其外部类的引用。

   在上面的例子中有点难以察觉内存泄露,那么下面的例子就非常的明显了。


 

private Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
    }
};

@Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
    super.onCreate(savedInstanceState, persistentState);
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {

        }
    },1000 * 60);
    
    finish();
}
 

     分析上面的代码,我们执行了finsh();被延迟的消息会在被处理之前存在于,主线程消息队列中10分钟,而这个消息中又包含了handler的引用,而handler又是一个匿名内部类的实例,其持有外面的activity的引用,所以activity中很多资源无法回收,这就是我们常说的内存泄露。

     要解决这种问题,思路就是避免使用非静态内部类,继承Handler时,要么是放在单独的类文件中,要么就是使用静态内部类。因为静态的内部类不会持有外部类的引用,所以不会导致外部类的实例内存泄露。当你需要在静态内部类中调用外部的activty时,我们可以使用弱引用来处理。另外关于同样需要将Runnable设置为静态的成员属性,注意;一个静态的匿名内部类实例不会持有外部类的引用。修改后不会导致内存泄露。

     

private static class MyHandler extends Handler{

    private final WeakReference<MainActivty> mWeakReference;

    private MyHandler(MainActivty mainActivty) {
        mWeakReference = new WeakReference<MainActivty>(mainActivty);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        MainActivty mainActivty = mWeakReference.get();
        if(mainActivty != null){
            //
        }
    }
}

private final MyHandler mMyHandler = new MyHandler(this);

public static Runnable sRunnable = new Runnable() {
    @Override
    public void run() {
       //
    }
};

@Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
    super.onCreate(savedInstanceState, persistentState);
    
    mMyHandler.postDelayed(sRunnable,1000 * 60);
    finish();
}

内部类构造外部类传引用:http://droidyue.com/blog/2014/10/02/the-private-modifier-in-java/


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值