AndroidでHandlerがメモリの漏洩を引き起こす可能性があります

1339 ワード

まずコードを見てみましょう.
1. private Handler mHandler = new Handler() {  
2.         @Override  
3.         public void handleMessage(Message msg) {  
4.             // ...  
5.          }  
6.     }; 

このような書き方はeclipseがleakのヒントを与えるThis Handler class should be static or leaks might occur...、メモリリークが発生する可能性があることを示します.1)Handlerオブジェクトがプライマリスレッドに作成されると、Looperのmessage queueに関連付けられます.メッセージキューにMessageが追加するとMessageは現在のHandler参照を保持し、Looperが現在のメッセージに処理するとHandler#handleMessage(Message)が呼び出される.2)javaでは、no-staticの内部クラスが現在のクラスの参照を暗黙的に保持します.staticのクラスはありません.3)まとめ:非静的内部クラスHandlerは外部クラスオブジェクトの参照を持つため,HandlerはMessage処理によりメモリに常駐する可能性がある.これにより、外部のActivityやServiceが破棄された後、GCに回収されず、メモリが漏れることもあります.
このため,外部クラスの漏洩を避けるためには,Handlerをstaticネストクラスとして宣言し,外部クラスへの弱い適用を用いるべきである.
1. static class MsgHandler extends Handler {  
2.     private WeakReference<Activity> mActivity;  
3.   
4.     MsgHandler(Activity activity) {  
5.         mActivity = new WeakReference<Activity>(activity);  
6.     }  
7.   
8.     @Override  
9.     public void handleMessage(Message msg) {  
10.         Activity activity = mActivity.get();  
11.         if (activity != null) {  
12.             activity.handleMessage(msg);  
13.         }  
14.     }  
15. }  
16.   
17. private Handler mHandler = new MsgHandler(this);