ホームページ > Java > &#&チュートリアル > Java ハンドラー同期バリアのサンプル コード分析

Java ハンドラー同期バリアのサンプル コード分析

WBOY
リリース: 2023-05-03 18:52:07
転載
914 人が閲覧しました

1. View の読み込みと描画のプロセスには、コレオグラファー クラス mChoreographer があります。

mTraversalBarrier = mHandler.getLooper().postSyncBarrier();同期バリア メッセージを MessageQueue に挿入します。msg.target==null メッセージ、戻り値 mTraversalBarrier は int トークン値です。

  void scheduleTraversals() {
    if (!mTraversalScheduled) {
      mTraversalScheduled = true;
       //向消息队列插入一个同步屏障的消息。msg.target==null的消息
             mTraversalBarrier = mHandler.getLooper().postSyncBarrier();
             mChoreographer.postCallback(
                  Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
    }
  }
ログイン後にコピー

mChoreographer.postCallback() メソッドは、mTraversalRunnable のコードを実行します。

mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);これにより、上記で生成されたトークン値に基づいて、MessageQueue 内の同期バリア メッセージが削除されます。

 final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
 final class TraversalRunnable implements Runnable {
            @Override
            public void run() {
                doTraversal();
            }
  }
   void doTraversal() {
      if (mTraversalScheduled) {
          mTraversalScheduled = false;
          //移除同步屏障消息
          mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);
          //在这个方法中会调用 measure layout draw,view的绘制绘制流程的方法
          performTraversals();
      }
    }
ログイン後にコピー

このコード行 mHandler.getLooper().postSyncBarrier() を見て、システムがそれをどのように処理するかを見てみましょう。

ハンドラーが設定されていないメッセージを取得しました。

int enqueueSyncBarrier(long when) {
        // Enqueue a new sync barrier token.
        // We don't need to wake the queue because the purpose of a barrier is to stall it.
        synchronized (this) {
            final int token = mNextBarrierToken++;
            // 这个msg.target没有被赋值
            final Message msg = Message.obtain();
            msg.markInUse();
            msg.when = when;
            msg.arg1 = token;
            Message prev = null;
            Message p = mMessages;
            if (when != 0) {
                while (p != null && p.when <= when) {
                    prev = p;
                    p = p.next;
                }
            }
            if (prev != null) { // invariant: p == prev.next
                msg.next = p;
                prev.next = msg;
            } else {
                msg.next = p;
                mMessages = msg;
            }
            return token;
        }
    }
ログイン後にコピー

通常、メッセージはハンドラーを通じて送信され、ハンドラーを空にすることはできません。

 boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
   ...........
}
ログイン後にコピー

なぜシステムは空のハンドラーを含むメッセージを送信するのでしょうか?

まず、同期バリア メッセージを送信した後に mChoreographer が何をしたかを見てみましょう。

別の非同期メッセージが送信されました: msg.setAsynchronous(true)。このメッセージのハンドラーは null ではありません。

private void postCallbackDelayedInternal(int callbackType,
            Object action, Object token, long delayMillis) {
      synchronized (mLock) {
            final long now = SystemClock.uptimeMillis();
            final long dueTime = now + delayMillis;
            mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
            if (dueTime <= now) {
                scheduleFrameLocked(now);
            } else {
                Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
                msg.arg1 = callbackType;
                //将消息设置为异步消息
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, dueTime);
            }
        }
}
ログイン後にコピー

次に、MessageQueue がメッセージを削除する方法と、この同期バリア メッセージを処理する方法を見てみましょう。

 Message next() {
            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                //如果msg.target==null说明我们已经向消息队里中插入了一条屏障消息。
                //此时会进入到这个循环中,找到msg.isAsynchronous==true的异步消息。
                //通常我们发送的都是同步消息isAsynchronous = false的,并且msg.target不能为null的。
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());//msg.isAsynchronous==true时结束循环,说明找到了这个异步消息。
                }
                if (msg != null) {//找到了同步屏障的异步消息后,直接返回
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (false) Log.v("MessageQueue", "Returning message: " + msg);
                        return msg;
                    }
                } else {//没有找到的话则进入休眠直到下一次被唤醒
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }
        }
    }
ログイン後にコピー

キャンセルする場合は、まず msg.target が null かどうかを確認し、次に while ループを通過して msg.isAsynchronous() == true というメッセージを見つけます。それが上記で送信された非同期メッセージです。通常、送信するメッセージは同期メッセージであるため、msg.setAsynchronous(true); は設定されません。

システムの目的は、この非同期メッセージを最初に処理することです。すべての同期メッセージはバリアと同様に後ろに配置されるため、このような操作は同期バリアと呼ばれ、同期バリア メッセージの処理の方が優先されます。

コレオグラファー クラス mChoreographer は画面のレンダリングを担当するため、インターフェイスの更新頻度を確保するために最下層からの信号をタイムリーに処理する必要があります。

以上がJava ハンドラー同期バリアのサンプル コード分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート