AndroidシステムHandlerの使い方の概要


ApiDemoのサービス例を紹介する前にAndroidのスレッドについて説明する必要があります.
アプリケーションが起動すると、Androidシステムはこのアプリケーションのためにメインスレッド(Main Thread)を作成し、メインスレッドは対応するUIコントロールにメッセージを配布し、スクリーンペイントイベントを処理するので、メインスレッドはUIスレッドとも呼ばれ、イベントの処理は「Event Queue」と呼ばれるもので配布されます.例えば、画面上のボタンを押すと、UIスレッドは「Touch」イベントをそのボタンに通知し、ボタンはこの「Touch」イベントを受け入れてその状態を「押す」状態にし、Event Queueに「Invalidate」イベントを追加してそのボタンを再描画する必要があることを示す.UIスレッドは、Event Queueから要求イベントを定期的に取り出し、ボタンの再描画を通知します.
アプリケーションが起動すると、デフォルトでは1つのMain Threadしか実行されません.アプリケーションが設計されていない場合、この単一スレッドモデルはアプリケーションのパフォーマンスが低下する可能性があります.特に、ネットワーク操作などの時間のかかる操作など、すべての操作がこのUIスレッドで発生した場合、データベースアクセスはUIスレッドをブロックし、アプリケーションがユーザー入力に応答しないようにし、深刻な場合、AndroidはANR(アプリケーションが応答しない)対応ボックスを表示し、アプリケーションを強制的に終了させる.
したがって、ユーザーにタイムリーに応答するアプリケーションを設計する基本原則は、UIスレッドをブロックしないことです.時間のかかる操作があれば、ワークスレッド(worker thread)を起動して完了します.
ワークスレッドを使用する際にUIを更新する必要がある場合は、現在、ほとんどのシステムUIが単一スレッドモードに設計されていることに注意してください.すなわち、UIコンポーネント定義の操作は「Thread-Safe」ではなく、ワークスレッドなどの非UIスレッドで直接UIを更新することはできません.幸いなことに、Androidシステムは、非UIスレッドからUIを更新するための複数の種類または方法を提供しています.
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
Handler
AsyncTask
ここではHandlerの他のいくつかを少し詳しく紹介したほうが分かりやすいです.Android簡明開発チュートリアル19:スレッドBezier曲線を参照してください.
Androidは、作成された各Threadに関連付けられたMessage Queueを持つことができ、このThreadにHandlerオブジェクトを作成すると、このHandlerオブジェクトは、作成されたThreadのMessage Queueにメッセージを送信するために使用することができる.例えば、Main Thread(UI Thread)で作成されたHandlerは、UIスレッドごとにメッセージを送信するために使用することができる.
Handlerは2つのアクションを定義します.
1つは、post(Runnable)、postAtTime(Runnable、long)、postDelayed(Runnable、long)を呼び出すことによって主に実行されるアクション(Runnable)を定義することです.
2つ目は、sendEmptyMessage(int)、sendMessage(Message)、sendMessageAtTime(Message、long)を呼び出すことによって主に実行される別のThreadのEvent Queueにアクションを追加することである.
AdvancedPreferencesのHandlerに関連するコードを見てみましょう.
private Handler mHandler = new Handler();

mHandlerはAdvancedPreferences、AdvancedPreferencesはPreferenceActivityのサブクラス(UIコンポーネント)として定義され、mHandlerはUI ThreadのMessage Queueに関連付けられ、UIスレッドにメッセージまたはScheduleのRunnableを送信してUIスレッドで実行することができる.
 
private Runnable mForceCheckBoxRunnable = new Runnable() {
 public void run() {
 if (mCheckBoxPreference != null) {
 mCheckBoxPreference.setChecked(!mCheckBoxPreference.isChecked());
 }
 
 // Force toggle again in a second
 mHandler.postDelayed(this, 1000);
 }
};

上のコードはRunnableオブジェクトを定義し、コードmHandler.postDelayed(this, 1000); UIスレッドMessage Queueには、1秒ごとに自分自身を実行し、mCheckBoxPreferenceの状態を切り替え、再び1秒ごとに同じ操作を実行するように要求する要求が送信されます.UIスレッドは、イベントをMessage Queueから取り出して実行する(UIスレッドにおけるCheckboxの更新)ことにより、非UIスレッドからのUI更新動作を実現する.