(転)Looper,androidメッセージメカニズムの詳細

5577 ワード

今日他の人のコードを呼び出した時prepare()のエラーは、調査の結果、私が新しく開いたThreadでLooperを1回呼び出すだけであることが分かった.prepare()は、相手のコードにhandlerがメッセージを送信するために使用されているため、androidのメッセージメカニズムはThreadを単位としているため、私が新しく開いたこのThreadにはメッセージloopが確立されていないので、この言葉を呼び出して、このThreadのloopをメインスレッドに追加する必要があります.詳細な説明は雲の中を歩いているブログから引用され、ブロガーの説明に感謝します.
http://my.unix-center.net/~Simon_fu/?p=652これは原文linkです
 
 
以下の内容はすべて転載です.
 
Androidメッセージ処理システム-Looper、Handler、Threadを深く理解する
2010 9月11日作者:シモンfu
ディレクトリ:組み込み型、テクノロジーコメント:8つのコメントWindowsプログラミングに詳しい方は、Windowsプログラムがメッセージ駆動であり、グローバルなメッセージループシステムがあることを知っているかもしれません.Androidアプリケーションもメッセージドライバであり、メッセージループメカニズムを提供する必要があります.実際、グーグルはWindowsのメッセージサイクルメカニズムを参考にしており、Androidシステムでもメッセージサイクルメカニズムを実現している.AndroidはLooper、Handlerによってメッセージループメカニズムを実現し、Androidメッセージループはスレッド向けである(各スレッドには独自のメッセージキューとメッセージループがある).Androidメッセージ処理システムの原理を詳しく紹介します.
AndroidシステムではLooperがスレッドのメッセージキューとメッセージループを管理しています.具体的にはLooperのソースコードを参照してください.Loopを通ることができます.myLooper()は、現在のスレッドのLooperオブジェクトを得る、Loop.getMainLooper()は、現在のプロセスのメインスレッドのLooperオブジェクトを取得できます.
前述したAndroidシステムのメッセージキューとメッセージループはいずれも特定のスレッドに対して行われており、1つのスレッドは1つのメッセージキューと1つのメッセージループ(Looper)が存在してもよく、特定のスレッドのメッセージは本スレッドにしか配布できず、スレッド間、プロセス間通信ができない.しかし、作成するワークスレッドのデフォルトはメッセージループとメッセージキューがないため、メッセージキューとメッセージループをスレッドに持たせるには、まずLooperをスレッドで呼び出す必要がある.prepare()はメッセージキューを作成し、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();
      }
  }

これにより、スレッドにはメッセージ処理メカニズムがあり、Handlerでメッセージ処理を行います.
ActivityはUIスレッドで、プライマリスレッドで実行され、Androidシステムは起動時にActivityのメッセージキューとメッセージループ(Looper)を作成します.詳細はActivity Threadを参照してください.JAvaファイル.
Handlerの役割は、メッセージを特定の(Looper)メッセージキューに追加し、そのメッセージキュー内のメッセージを配布し、処理することである.Handlerを作成するときにLooperオブジェクトを指定し、指定しない場合は現在のスレッドのLooperを使用して作成します.詳細はLooperのソースコードを参照してください.
Activity、Looper、Handlerの関係を下図に示します.
1つのActivityでは、複数の作業スレッドまたは他のコンポーネントを作成できます.これらのスレッドまたはコンポーネントがActivityのプライマリ・スレッド・メッセージ・キューにメッセージを入れると、メッセージはプライマリ・スレッドで処理されます.メインスレッドは一般的にインタフェースの更新操作を担当し、Androidシステムのwegetはスレッドが安全ではないため、この方式はAndroidインタフェースの更新をうまく実現することができる.Androidシステムではこの方式が広く使われている.
では、別のスレッドはどのようにしてメインスレッドのメッセージキューにメッセージを入れますか?答えはHandleオブジェクトによって,HandlerオブジェクトがメインスレッドのLooperで作成される限り,HandlerのsendMessageなどのインタフェースを呼び出すと,メッセージをキューに入れるのはすべてメインスレッドに入れるメッセージキューである.handlerのhandleMessageインタフェースは、Handlerマスタースレッドで呼び出され、メッセージが処理されます.
スレッド同期の問題については、次の例を参照してHandlerオブジェクトのスレッドモデルを理解してください.
1、まずMyHandlerプロジェクトを作成する.
2、MyHandler.JAvaには、次のコードが追加されています.
package com.simon;

import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.os.Handler;

public class MyHandler extends Activity {
	static final String TAG = "Handler";
	Handler h = new Handler(){
    	public void handleMessage (Message msg)
    	{
    		switch(msg.what)
    		{
    		case HANDLER_TEST:
    			Log.d(TAG, "The handler thread id = " + Thread.currentThread().getId() + "/n");
    			break;
    		}
    	}
    };

	static final int HANDLER_TEST = 1;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "The main thread id = " + Thread.currentThread().getId() + "/n");

        new myThread().start();
        setContentView(R.layout.main);
    }

    class myThread extends Thread
    {
    	public void run()
    	{
    		Message msg = new Message();
    		msg.what = HANDLER_TEST;
    		h.sendMessage(msg);
    		Log.d(TAG, "The worker thread id = " + Thread.currentThread().getId() + "/n");
    	}
    }
}

この例では,主に印刷を行い,この処理機構の各モジュールのスレッド状況を示す.以下は私の機械の運行結果です.
09-10 23:40:51.478: DEBUG/Handler(302): The main thread id = 1
09-10 23:40:51.569: DEBUG/Handler(302): The worker thread id = 8
09-10 23:40:52.128: DEBUG/Handler(302): The handler thread id = 1

メッセージ処理はプライマリ・スレッドで処理され、メッセージ処理関数では、リフレッシュ・インタフェースを含むプライマリ・スレッド内の任意のリソースを安全に呼び出すことができることがわかります.ワークスレッドとプライマリスレッドは異なるスレッドで実行されるため、この2つのスレッド間の競合関係に注意する必要があります.
前の例では、ワークスレッドでプライマリスレッドhandlerオブジェクトにアクセスし、handlerを呼び出すオブジェクトでメッセージキューにメッセージを追加したことに気づくかもしれません.この過程でメッセージキューのデータが一致しないという問題は発生しませんか?答えはhandlerオブジェクトは問題ありません.handlerオブジェクトが管理するLooperオブジェクトはスレッドが安全で、メッセージキューへの参加やキューからのメッセージの読み出しに同期オブジェクトが保護されています.具体的にはLooperを参照してください.JAvaファイル.前の例ではhandlerオブジェクトは変更されていないので、handlerオブジェクトにデータが一致しないという問題は起こり得ません.
上記の分析から、以下の結論を得ることができます.
1、ワークスレッドでインタフェースをリフレッシュする場合は、handlerオブジェクトを使用して実装することを推奨します.
2、作業スレッドとメインスレッドの競合関係に注意してください.handlerオブジェクトは、プライマリ・スレッドでの構築が完了し(作業スレッドを起動してから変更しないでください.そうしないとデータが一致しません)、作業スレッドで送信メッセージSendMessageなどのインタフェースを安心して呼び出すことができます.
3、2に記載のhanlderオブジェクトを除く任意のプライマリスレッドのメンバー変数がワークスレッドで呼び出される場合、スレッド同期の問題を注意深く考慮する.必要に応じて同期オブジェクトを追加して変数を保護します.
4.handlerオブジェクトのhandleMessageインタフェースがメインスレッドで呼び出されます.この関数では、プライマリ・スレッド内の任意の変数と関数を安心して呼び出し、UIの更新を完了できます.
5、Androidの多くのAPIもHandlerというスレッド特性を利用して、コールバック関数の変種として、呼び出し者に通知している.これにより、Androidフレームワークは、スレッド同期の問題を心配することなく、呼び出し元のスレッドメッセージキューにメッセージを送信することができます.
Androidメッセージ処理メカニズムを深く理解することはアプリケーション開発にとって非常に重要であり、スレッド同期をより深く認識することもできます.以上は最近SimonがAndroidメッセージの処理メカニズムを学んだことをまとめたもので、間違いがあれば教えてください.
変換元:http://blog.csdn.net/xijiaohuangcao/article/details/6400814