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);

    }

}

相關文章
相關標籤/搜索