参考:Communicating with the UI thread | Android Developers
参考:Handler | Android Developers
参考:Looper | Android Developers
目次
Looper
Looper
は、Looper
が初期化されたスレッド内で作られたメッセージを順に処理するオブジェクトです。
Activity などのコンポーネントでは、標準でこのLooper
が UI スレッド上で初期化されます。これによって、Activity や Fragment で受け取った UI のイベントをメッセージとしてLooper
に投げると、メインスレッド上でそのメッセージが実行されるようになります。
メインスレッド用のLooper
を取得する場合は以下のようにします。
Looper looper = Looper.getMainLooper();
Looper
は、その初期化を実行したスレッド内でメッセージを順に処理するように振舞うので、UI スレッドでない別のスレッドにも適用できます。
こうすることで、別スレッドにおいても、何らかのイベントをメッセージとして受け付けることが出来るようになります。
public class MyThread extends Thread {
@Override
public void run() {
Looper.prepare(); // 初期化
// ...
Looper.loop(); // メッセージキューを開始
}
}
Handler
Looper
の仕組みによって、メッセージを受け付けて順に処理できるようになりますが、一方で、Looper
に対してメッセージを送る役割を持つものが必要になります。
この、Looper
に対してメッセージを送る役割を担っているのがHandler
です。
多くは、別スレッドから UI スレッドへメッセージを送ることで、別スレッド内で UI の更新を促す為の仕組みとして用いられます。
下記のようにHandler
インスタンスを生成すると、生成したインスタンスのLooper
にメッセージを送るHandler
が作られます。
Handler handler = new Handler();
もし、メインスレッドの Looper にメッセージを送るHandler
インスタンスを生成する場合は、以下のようにします。
Handler handler = new Handler(Looper.getMainLooper());
メッセージを作成し、その内容をLooper
のキューに積んで実行させるには、以下のようにします。
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
// メインスレッド上で実行させたい内容
}
});
HandlerThread
Handler
を内部に持ち、Looper
が動作していて、適宜そのLooper
にメッセージを積み上げて処理することの出来る特別なThread
です。
HandlerThread
のインスタンスが生成された時、Looper#prepare()
が呼び出され、Looper
の動作が始まります。この後、このスレッド用にHandler
が生成され、他のスレッドとのメッセージのやり取りが出来るようになります。
IntentService
は内部的にHandlerThread
を使用しており、Context#startService(Intent)
で渡されたIntent
を順にHandler
を経由してHandlerThread
に渡しています。これによって、簡易的なジョブキューの仕組みが実現されています。