Handler警告

2092 ワード

警告メッセージ:Handler Class Should be static or Leaks Occur
この警告についてはこれまで気づかなかったが,いくつかのテストでHandlerを使用したことがある.今でも大きな問題だと気づきました汗.
まず、Handlerはメモリ漏洩のリスクがあるという意味ですが、なぜですか?
通常のサボりの書き方:
private Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        TextView textView = (TextView) findViewById(R.id.final_txt);
        textView.setText(msg.getData().getString("msg"));
    }
};

この匿名実装は一般的にActivityに直接定義されていますが、ここではJavaの観点から、私たちのHandlerはActivityの匿名内部クラスであり、内部クラスは外部クラスのインスタンスをデフォルトで持っています.外部クラスは現在のActivityであり、一般的にLooperにメッセージを送信するメッセージにはHandlerリファレンス(handlerMessageメソッドを呼び出す必要がある)が含まれていますが、LooperのライフサイクルはApplicationと一致しています.その結果、より長いライフサイクルを持つLooperはActivityインスタンスを持ち、メッセージにActivityリファレンスが遅延すると解放できない(この場合、このActivityはgcによって回収できない)ため、メモリが漏洩する(参照:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1106/1922.html).
この問題を解決する方法:
  • サボらないで、Handlerを別のclassファイルに書きます.
  • は、Handerを静的内部クラスとして定義する(静的内部クラスは外部クラス参照を持たない).
  • private static class MyHandler extends Handler {
        private final WeakReference<ThiredActivity> mActivity;
    
        private MyHandler(ThiredActivity mActivity) {
            this.mActivity = new WeakReference<ThiredActivity>(mActivity);
        }
    
        @Override
        public void handleMessage(Message msg) {
            ThiredActivity activity = mActivity.get();
            if (activity != null) {
                TextView textView = (TextView) activity.findViewById(R.id.final_txt);
                textView.setText(msg.getData().getString("msg"));
            }
        }
    }

    ここでは、Activityインスタンスを保持するために弱いインデックスを使用します.弱参照:http://blog.csdn.net/jinhuiyu/article/details/3709767
    この方法は同様にThreadリークの問題を解決することができ、以下を参照してください.http://blog.csdn.net/zhuanglonghai/article/details/37909553
        3.最後に、onDestroyで未処理のメッセージをすべてキャンセルするのも最も簡単です.
    mHandler.removeCallbacksAndMessages(null);

    Activity destroyの後で処理しなければならない処理がある場合は、Handlerの代わりにサービスなどの他の方法を使用することも考えられます.
    メモリリークリファレンス:http://www.cnblogs.com/qianxudetianxia/p/3645106.html