Handler和内部类的正确用法

PS:本文摘抄自《Android高级进阶》,仅供学习使用ide

  Android代码中涉及线程间通讯的地方常常会使用Handler,典型的代码结构以下。oop

1post

2学习

3this

4spa

5.net

6线程

7code

8对象

9

public class HandlerActivity extends Activity{

    //可能引入内存泄漏的用法

    private final Handler mLeakyHandler = new Handler(){

        @Orrvide

        public void handleMessage(Mesage msg){

            //...

        }

    };

}

  使用Android Lint分析这段代码,会违反检测项AndroidLintHandlerLeak,获得以下提示。

1

This Handler class should be static or leaks might occur.

  那么产生内存泄漏的缘由多是什么呢?咱们知道,Handler是和Looper以及MessageQueue一块儿工做的,在Android中,一个应用启动后,系统默认会建立一个为主线程服务的Looper对象,该Looper对象用于处理主线程的全部Message对象,它的生命周期贯穿于整个应用的生命周期。在主线程中使用的Handler都会默认绑定到这个Looper对象。在主线程中建立Handler对象,它会当即关联到主线程Looper对象的MessageQueue,这时发送到MessageQueue中的Message对象都会只有这个Handler对象的引用,这样在Looper处理消息时常能回调到Handler的handlerMessage方法。所以,若是Message尚未被处理完成,那么Handler对象也就不会被垃圾回收。

  在上面的代码中,将Handler的实例声明为HandlerActivity类的内部类。而在Java语言中,非静态内部匿名类会持有外部类的一个隐式的引用,这样就可能会致使外部类没法被垃圾回收。所以,最终因为MessageQueue中Message还没处理完成,就会持有Handler对象的引用,而非静态的Handler对象会持有外部类HandlerActivity的引用,这个Activity没法被垃圾回收,从而致使内存泄漏。

  一个明显的会引入内存泄漏的例子以下。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public class HandlerActivity extends Activity{

    //可能引入内存泄漏的用法

    private final Handler mLeakyHandler = new Handler(){

        @Orrivide

        public void handleMessage(Mesage msg){

            //...

        }

    };

    @Orrivide

    protected void onCreate(Bundle savedInstanceState){

        super.onCreate(savedInstanceState);

        //延迟5分钟发送消息

        mLeakyHandler.postDelayed(new Runnable(){

            @Orrivide

            public void run(){/* ... */}

        }, 1000*60*5);

    }

}

  因为消息延长5分钟,所以,当用户进入这个Activity并退出后,在消息发送并处理完成以前,这个Activity是不会被系统回收的(系统内存确实不够使用的状况例外)。

  若是解决呢。有两个方案。

  • 在子线程中使用Handler,这时须要开发者本身建立一个Looper对象,这个Looper对象的生命周期同通常的Java对象,所以这种用法没有问题。
  • 将Handler生命为静态的内部类,前面说过,静态内部类不会持有外部类的引用,英寸,野不会引发内存泄漏,经典用法的代码以下。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

public class HandlerAcitivity extends Activity{

    //声明一个静态的Handler内部类,并持有外部类的弱引用

    private static class InnerHandler extends Handler{

        private final WeakReference<HandlerAcitivity> mActivity;

        public InnerHandler(HandlerAcitivity activity){

            mActivity = new WeakReference<HandlerAcitivity>(activity);

        }

        @Override

        public void handleMessage(Message msg){

            HandlerAcitivity activity = mActivity.get();

            if(activity!=null){

                //...

            }

        }

    }

    private final InnerHandler mHandler = new InnerHandler(this);

    //静态的匿名内部类不会持有外部类的引用

    private static final Runnable sRunnable = new Runnable(){

        @Override

        public void run(){

            //...

        }

    };

    @Override

    protected void onCreate(Bundle savedInstanceState){

        super.onCreate(savedInstanceState);

        //延迟5分钟发送消息

        mHandler.postDelay(sRunnable, 1000*60*5);

    }

}

相关文章
相关标签/搜索