簡単な答え:それらはすべて同じスレッドで実行されます。ライフサイクル コールバックからインスタンス化された場合Activity
、それらはすべてメイン UI スレッドで実行されます。
長い答え:
スレッドにはLooper
、 を含む がある場合がありますMessageQueue
。この機能を使用するにはLooper
、 (静的) を呼び出して現在のスレッドで を作成し、 (静的)Looper.prepare()
を呼び出してループを開始する必要がありますLooper.loop()
。Looper
これらは、スレッドごとに 1 つしかないと想定されているため、静的です。
通常、への呼び出しloop()
はしばらく戻りませんMessageQueue
が、 からメッセージ (「タスク」、「コマンド」、または呼び出したいもの) を取得し続け、それらを個別に処理します (たとえばRunnable
、メッセージに含まれる a を呼び戻すことによって)。キューにメッセージが残っていない場合、スレッドは新しいメッセージがあるまでブロックされます。a を停止するLooper
には、それを呼び出す必要がありますquit()
(これはおそらくループをすぐに停止するのではなく、ループから定期的にチェックされるプライベート フラグを設定し、停止するように通知します)。
ただし、メッセージをキューに直接追加することはできません。代わりにMessageQueue.IdleHandler
、コールバックを待機するためにを登録しqueueIdle()
ます。このコールバックで、何かを実行するかどうかを決定できます。すべてのハンドラが順番に呼び出されます。(したがって、「キュー」は実際にはキューではなく、代わりに定期的に呼び出されるコールバックのコレクションです。)
前の段落に関する注意:これは私が実際に推測したものです。それに関するドキュメントは見つかりませんでしたが、それは理にかなっています。
更新: ahcoxのコメントと彼の回答を参照してください。
これは大変な作業なので、フレームワークはHandler
物事を単純化するためのクラスを提供します。インスタンスを作成するHandler
と、(デフォルトで)Looper
現在のスレッドにすでにアタッチされている にバインドされます。( は、おそらく への参照を に格納しているため、先に呼び出したので、何にアタッチするかをHandler
知っています。)Looper
prepare()
Looper
ThreadLocal
を使用すると、 「メッセージをスレッドのメッセージキューに入れる」(いわば)ためにHandler
呼び出すことができます。post()
はHandler
すべてのIdleHandler
コールバックを処理し、投稿されたものが確実にRunnable
実行されるようにします。(遅れて投稿した場合は、時間がすでに正しいかどうかも確認する場合があります。)
明確にするために: ループしているスレッドに実際に何かをさせる唯一の方法は、そのループにメッセージを投稿することです。これは、ルーパーで quit() を呼び出すまで有効です。
Android UI スレッドについて:Looper
ある時点 (おそらくアクティビティなどが作成される前) で、フレームワークは(を含む) をセットアップしてMessageQueue
開始しました。この時点から、UI スレッドで発生するすべてのことは、そのループを介して行われます。これには、アクティビティのライフサイクル管理などが含まれます。オーバーライドするすべてのコールバック ( onCreate()
、onDestroy()
...) は、少なくともそのループから間接的にディスパッチされます。たとえば、例外のスタック トレースで確認できます。(試してみることができます。int a = 1 / 0;
どこかに書いてくださいonCreate()
...)
これが理にかなっていることを願っています。以前はわかりづらくてすみません。