欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

This Handler class should be static or leaks might occur (anonymous android.os.Handler) less

程序员文章站 2022-07-14 18:26:06
...

在Java 中:非静态的内部类和匿名类都会隐式的持有一份对外部类的引用,而静态的内部类则不会包含对外部类的引用。

android studio最新版本有个很好的功能就是可以自动检测出代码中内存泄漏等问题
今天说一下Handler出现内存泄漏的原因,以及解决方法

In Android, Handler classes should be static or leaks might occur. Messages enqueued on the application thread’s MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class.

大体翻译如下:

Handler 类应该应该为static类型,否则有可能造成泄露。在程序消息队列中排队的消息保持了对目标Handler类的应用。如果Handler是个内部类,那 么它也会保持它所在的外部类的引用。为了避免泄露这个外部类,应该将Handler声明为static嵌套类,并且使用对外部类的弱应用。

发生内存泄漏的情况举个例子:

private Handler mHandler1 = new Handler(){  
   public void handleMessage(Message msg) {  
         
   };  
};

当app启动的时候,Android Framework会为主线程创建一个Looper对象,这个Looper对象贯穿这个App的整个生命周期,它实现了一个消息队列(Message Queue),并且开启一个循环来处理Message对象,而Framework的主要事件都包含着内部Message对象,当这些事件被触发的时候,Message对象会被加到消息队列中执行。当一个Handler被实例化时,它将和主线程Looper对象的消息队列息息相关,被推倒消息队列中的Message对象将持有一个Handler的引用以便于Looper处理到这个Message的时候,Framework执行handler的handleMessage(Message)方法。

在Java 中:非静态的内部类和匿名类都会隐式的持有一份对外部类的引用,而静态的内部类则不会包含对外部类的引用。

解决这个问题最简单的方法:使用官方给的方法,

private Handler mHandler2 = new Handler(new Handler.Callback() {  
         
       @Override  
       public boolean handleMessage(Message msg) {  
           return false;  
       }  
   }); 

或者说是定义一个静态类

static class MyHandler extends Handler {  
    WeakReference<OuterClass> outerClass;  
 
    MyHandler(OuterClass activity) {  
        outerClass = new WeakReference<OuterClass>(activity);  
    }  
 
    @Override  
    public void handleMessage(android.os.Message msg) {  
        OuterClass theClass = outerClass.get();  
        switch (msg.what) {  
        case 0: {  
            //使用theClass访问外部类成员和方法  
            break;  
        }  
        default: {  
            Log.w(TAG, "未知的Handler Message:" + msg.what);  
        }  
        }  
 
    }  
}  

我一般都是用第一种方法,官方既然已经给出,显然不存在匿名内部类

上一篇: 浅谈new/delete

下一篇: Android Handler