web-dev-qa-db-ja.com

ハンドラークラスの動作Android

私はAndroid=に不慣れで、公式のAndroidウェブサイトでデモアプリケーションを読んでいました。そして、次の名前のHandlerクラスのメソッドに出会いましたpostDelayed(Runnable r, long milliseconds)

誰もがこの方法が何をするのか説明できますか?

28
Rajat

documentation が表示されます。

しかし、ドキュメントを理解するには、まずいくつかの概念を理解する必要があります。 メッセージ、メッセージキュー、ハンドラー、およびルーパー 、およびそれらの 関係

以下は、ルーパーがどのように機能するかを示しています。ルーパーがスレッドローカルオブジェクトであり、MessageQueueとの関係であることを示しています。

class Looper{
    public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }

    public static final void loop() {
        Looper me = myLooper();
        MessageQueue queue = me.mQueue;
        while (true) {
            Message msg = queue.next(); // might block
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }
                msg.target.dispatchMessage(msg);
                msg.recycle();
            }
        }
    }
}

いくつかの注意:

ルーパーは、すべてのスレッドが1つのルーパーを持つようなスレッドローカルオブジェクトです。すべてのルーパーはメッセージキューに関連付けられています。ルーパーは継続的にキューからmessagese( "tasks"、 "commands"またはあなたが呼び出したいもの)を取得し、そのメッセージをそのターゲットに処理するハンドラーであるターゲットにディスパッチします(たとえば、に含まれるRunnableを呼び出すことにより)メッセージ)。キューにメッセージが残っていない場合、スレッドは新しいメッセージがあるまでブロックされます。ルーパーを停止するには、その上でquit()を呼び出す必要があります(ループをすぐに停止するのではなく、ループから定期的にチェックされるプライベートフラグを設定し、停止するように通知します)。

Androidフレームワークは、物事を簡素化するためのHandlerクラスを提供します。 Handlerインスタンスを作成すると、それは(デフォルトで)現在のスレッドにすでにアタッチされているLooperにバインドされます。 (先にprepare()を呼び出したため、HandlerはどのLooperにアタッチするかを認識しています。これにより、ThreadLocalにLooperへの参照が格納されました。)

ハンドラーを使用すると、post()を呼び出して「スレッドのメッセージキューにメッセージを書き込む」ことができます(いわば)。ハンドラーはすべてのIdleHandlerコールバックを処理し、ポストされたRunnableが実行されることを確認します。 (遅延して投稿した場合は、タイミングが既に正しいかどうかもチェックする場合があります。)

次のコードは、それらを使用する一般的な方法を示しています。

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();
  }

}

ハンドラーは、Androidサービスで広く使用されています。Androidアプリケーション間通信をサポートしています。通常、マルチスレッドを処理する必要のないサービスを実装する場合、クライアントからの呼び出しごとにコールバックを受信するハンドラ。次に、BinderオブジェクトであるMessengerオブジェクト(ハンドラへの参照)を作成し、このサービスをバインドするときにこのオブジェクトをクライアントに返します。したがって、クライアントはこのメッセンジャーを使用してメッセージを(スレッドローカルキューに送信し、ルーパー経由でハンドラーに送信)、このサービスに送信し、ハンドラーでメッセージを処理します。コードサンプルが添付されています。

public class MessengerService extends Service {
    /** Command to the service to display a message */
    static final int MSG_SAY_HELLO = 1;

    /**
     * Handler of incoming messages from clients.
     */
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }


    final Messenger mMessenger = new Messenger(new IncomingHandler());

    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }
}
51
StarPinkER

postDelayed (Runnable r, long delayMillis)

Runnable rメッセージキューに追加され、指定された時間が経過した後に実行されます。 runnableは、このハンドラーが接続されているスレッドで実行されます。

  • Runnable実行可能なコマンドを表します。

  • delayMillisは、それが実行されるまでの時間を表します。

基本的に、指定した時間(delayMillis)の間、コマンド(一部のコードは多分)の実行を遅らせ、指定した時間の後にコマンドを実行します。

6