Android Handler的正确使用

        在Android开发有时候会使用到Handler,但是每次新建一个对象的时候,开发工具都会报一个黄色警告。以前没做过大项目,觉得只要不是Error就可以不关心。但是上次出了一个内存泄露之后,不敢大意了,对于可能出现内存泄露的都需要认真处理下。查了下,这个黄色警告就是因为这样创建Handler有可能会出现内存泄露才报的。所以这里记录一下如何避免创建Handler发生内存泄露。
        正常以前的创建方式是这样的:
        private Handler handler = new Handler(){
                @Overwrite
                public void handMessage(){

                }
        }; 
黄色警告内容如下:
    This Handler class should be static or leaks might occur (anonymous android.os.Handler) less... (Ctrl+F1)
Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected. If the Handler is using a Looper or MessageQueue for a thread other than the main thread, then there is no issue. If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler declaration, as follows: Declare the Handler as a static class; In the outer class, instantiate a WeakReference to the outer class and pass this object to your Handler when you instantiate the Handler; Make all references to members of the outer class using the WeakReference object.

大致意思就是,这样创建Hanler对象可能会引发内存泄露,应该定义成静态内部类。

解释之前:在Java中非静态内部类和匿名内部类都会隐式拥有外部类的引用,而静态内部类则不会拥有外部类的引用
而Handler为什么会有可能出现内存泄露呢?

是因为当像上面创建Handler的方法一样创建Handler对象的时候,这个Handler被声明为内部类,而它可以拥有外部类的引用。所以当handler定义在activity里面的主线程时候,这个handler就拥有了activity的引用。那么当activity销毁了之后,如果handler关联的主线程的MessageQueue中有一个延时很长时间的Message的时候,因为MessageQueue对象有handler的引用,而handler又有activity的引用,activity是主线程,它又有Message Queue对象的引用,这就会导致Java垃圾回收机制一直回收不了这些内存,就会导致内存泄露。

注意:上面这句”当handler定义在activity里面的主线程时候 “,默认handler是使用activity主线程里面的MessageQueue对象。否则,如果handler在activity中使用自定义的MessageQueue,上面的解释就不正确了。

当在activity中定义handler,并且handler使用的是主线程中MessageQueue的对象时,正确定义handler的方式是:

private static class MyHandler extends Handler {

    private WeakReference<MainActivity> activityWeakReference ;

    public MyHandler(MainActivity activity) {
        activityWeakReference = new WeakReference<MainActivity>(activity) ;
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg) ;
        MainActivity activity = activityWeakReference.get() ;
        if (activity != null) {

        }
    }
}


猜你喜欢

转载自blog.csdn.net/lin962792501/article/details/79109048
今日推荐