Handlerメッセージ構造の注意点

2919 ワード

参照リンク:Handlerのいくつかの使用姿勢を説明します.
handlerメカニズムは、スレッドのメッセージ伝達を簡単に処理することができますが、同時にhandlerを使用するには、注意すべき点があります.
この章を通して知ることができます.
  • は、ハードラー
  • をサブスレッドに使用する.
  • Handlerを使用してメモリの漏洩を避ける
  • サブスレッドでは、Handlerを使用します.
    一般的にはHandlerを使用する場合、メインスレッドで使用します.しかし、Handlerはサブスレッドでも使用できます.
            new Thread(()->{
               Handler threadHandler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        
                    }
                };
            }).start();
    
    ただし、直接にサブスレッドに初期化すると、Handlerに異常が発生します.
        java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
            at android.os.Handler.(Handler.java:204)
            at android.os.Handler.(Handler.java:132)
    
    Handler初期化はLooperが必要ですので、Looperを初期化する必要があります.
    new Thread(()->{
                Looper.prepare();
               Handler  threadHandler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        switch (msg.what){
                            case 1:
                                Log.i("threadHandler",(CharSequence) msg.obj + "23333");
                        }
                    }
                };
    //            Looper.loop();
            }).start();
    
    これでエラーはないですが、これではメッセージを処理できません.Looper.loop()メソッドを呼び出してループ処理メッセージを開始する必要があります.
    Handlerを使用する場合はメモリの漏洩を避ける
    私たちは普段ハンドルを使う時は、直接的に実用化して、他のところで使うことが多いです.
    private Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                   //     
            }
        };
    
    しかし、それはメモリ漏れです.handlerは非静的な匿名の内部クラスであるため、外部クラスの引用をデフォルトで保持しています.外部activityが突然閉鎖された場合、Message Queのメッセージはまだ処理されていません.メモリ漏れの原因となります.MessageはHandlerオブジェクトを持っているため、Handlerは外部activityの引用を持っているため、外部activityは回収できなくなります.
    この問題を解決するには、外部Activityで静的な内部クラスを定義することができます.次に、外部クラスを持つ参照を弱引用に変更します.ごみを回収する時、弱い引用の対象を自動的に回収するからです.
    public class TextActivity extends AppCompatActivity {
    
        private MyHandler handler = new MyHandler(this);
    
        private static class MyHandler extends Handler {
            WeakReference mWeakActivity;
    
            public MyHandler(HandlerActivity activity) {
                this.mWeakActivity = new WeakReference(activity);
            }
    
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                final TextActivity mActivity = mWeakActivity.get();
                if (mActivity != null) {
                    //     
                }
            }
        }
    
    }
    
    もう一つの簡単な方法があります.外部のActivityが廃棄された時にメッセージのキューを削除することです.handlerを釈放したのと同じです.ゴミの回収はスムーズに行われます.
        @Override
        protected void onDestroy() {
            super.onDestroy();
            handler.removeCallbacksAndMessages(null);
        }