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()はメッセージループに入ります.このスレッドには、次のようなメッセージ・ループ・メカニズムがあります.
実際にメッセージキューもLooperで作成されていますが、Looperのloop()メソッドを見てみると、このメソッドはメッセージループ用に使用されます.
Handlerのコンストラクション関数を見てみましょう.Handlerのコンストラクション関数では、現在のスレッドのLooperオブジェクトとメッセージキューが得られます.メッセージキューもlooperから入手しましたが、さっきお話ししました.
handlerにはいくつかの重要な方法があります.
handleMessage//メッセージの処理
dispatchMessage//メッセージの配布
sendMessage//メッセージ送信
ここでandroidにおけるメッセージフローは,Handlerが現在のスレッドのLooper,MessageQueueを取得し,MessageQueueにメッセージを送信することをほぼ理解できる.Looperはメッセージをループし、msgを通過する.target.dispatchMessageは、メッセージを配信するために使用される(targetはhandlerであるべきである).そしてハンドラーhandlerMessageはメッセージを処理します.
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はメッセージを処理します.