AndroidのMessageQueue、Looper、Handlerとメッセージループ


Androidのactivityには様々なイベントがあり、これらのイベントは最終的にメッセージに変換されて処理される.androidのメッセージシステムは、*メッセージ送信*メッセージキュー*メッセージループ*メッセージ配信*メッセージ読み出しメッセージに対応する重要なクラスとして、メッセージキュー、メッセージループ、およびメッセージ処理に対応するMessageQueue、Looper、Handlerに関する.
 
Handlerクラス:Handlerは主にメッセージの送信と処理に使用されます.各handlerインスタンスは、スレッドとスレッドのメッセージキューに対応します.handlerオブジェクトを作成すると、handlerオブジェクトは作成されたスレッドに属し、プライマリ・スレッドにhandlerオブジェクトを作成するなど、スレッドのメッセージ・キューにバインドされます.handlerはプライマリ・スレッドにのみ属し、プライマリ・スレッドのメッセージ・キューにバインドされます.(もちろん、各スレッドには独自のメッセージキューがあり、androidではメッセージキューはスレッド向けです).これにより、handlerはメッセージをメッセージキューに送信し、メッセージキューのメッセージを処理することができる.リモート・ネットワークへのアクセス、ダウンロードなど、時間のかかる操作を実行すると、通常、新しいスレッドが起動して操作されます.uiスレッドに置かずに行うことで、androidの5秒に対応するANR異常がないことを防止できます.サブスレッドで返される結果をuiスレッドにどのように更新するかはhandlerで処理できます.プライマリ・スレッドでhandlerを定義し、プライマリ・スレッドhandlerを使用してサブスレッドのメッセージをプライマリ・スレッドに対応するメッセージ・キューに送信できます.メインスレッドでhandlerを通過する.handlerMessageはメッセージを処理しuiに更新できます.私たちはさっき言ったように、Handlerは主にメッセージを送信し、処理するために使われています.では、メッセージループ、キューはどこで管理されていますか.答えは:Looper、MessageQueueの中です.
Looperクラス:looperクラスは主にスレッドのメッセージループを開くために使用されます.デフォルトでは、システムは起動時にメインスレッドにメッセージループを作成します.他に新しく作成されたスレッドはありません.必要に応じて、そのスレッド内でLooperを呼び出すことができます.prepare()を使用してlooperオブジェクトを有効にし、Looperを呼び出します.loop()はメッセージループに入ります.このスレッドには、次のようなメッセージ・ループ・メカニズムがあります.
class LooperThread extends Thread {
        public Handler mHandler;
        
        public void run() {
            Looper.prepare();
            
            mHandler = new Handler() {
                public void handleMessage(Message msg) {
                    // process incoming messages here
                }
            };
            
            Looper.loop();
       }
    }

実際にメッセージキューもLooperで作成されていますが、Looperのloop()メソッドを見てみると、このメソッドはメッセージループ用に使用されます.
public static final void loop() {
         Looper me = myLooper(); //       Looper  
         MessageQueue queue = me.mQueue;  //           
        while (true) { //   true、      。    
            Message msg = queue.next(); // might block
              //if (!me.mRun) {
            //    break;
             //}
            if (msg != null) {
                if (msg.target == null) {
                     // No target is a magic identifier for the quit message.
                    return;
               }
                  if (me.mLogging!= null) me.mLogging.println(
                        ">>>>> Dispatching to " + msg.target + " "
                        + msg.callback + ": " + msg.whclearForRecycleat
                         );
                 msg.target.dispatchMessage(msg); //    
                if (me.mLogging!= null) me.mLogging.println(
                         "<<<<< Finished to    " + msg.target + " "
                         + msg.callback);
                 msg.recycle(); //        ,         
             }
         }
     }

Handlerのコンストラクション関数を見てみましょう.Handlerのコンストラクション関数では、現在のスレッドのLooperオブジェクトとメッセージキューが得られます.メッセージキューもlooperから入手しましたが、さっきお話ししました.
public Handler() {
         if (FIND_POTENTIAL_LEAKS) {
             final Class<? extends Handler> klass = getClass();
             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                     (klass.getModifiers() & Modifier.STATIC) == 0) {
                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                     klass.getCanonicalName());
             }
         } 
          // Handler             Looper  、     。       looper    
         mLooper = Looper.myLooper();
         if (mLooper == null) {
             throw new RuntimeException(
                 "Can't create handler inside thread that has not called Looper.prepare()");
         }
         mQueue = mLooper.mQueue;
         mCallback = null;
     }

handlerにはいくつかの重要な方法があります.
 
handleMessage//メッセージの処理
dispatchMessage//メッセージの配布
sendMessage//メッセージ送信
 
ここでandroidにおけるメッセージフローは,Handlerが現在のスレッドのLooper,MessageQueueを取得し,MessageQueueにメッセージを送信することをほぼ理解できる.Looperはメッセージをループし、msgを通過する.target.dispatchMessageは、メッセージを配信するために使用される(targetはhandlerであるべきである).そしてハンドラーhandlerMessageはメッセージを処理します.