Handler.createAsyn作用

结论

从API28开始,Handler类增加了静态方法createAsyn。主要作用是使所有通过这个Handler发送的Message,都会被设置为FLAG_ASYNCHRONOUS异步消息(默认是同步消息),在搭配消息屏障使用的情况下,会被优先调用。

原理

#Handler.java
	@NonNull
    public static Handler createAsync(@NonNull Looper looper) {
        if (looper == null) throw new NullPointerException("looper must not be null");
        return new Handler(looper, null, true);
    }
    @NonNull
    public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) {
        if (looper == null) throw new NullPointerException("looper must not be null");
        if (callback == null) throw new NullPointerException("callback must not be null");
        return new Handler(looper, callback, true);
    }

其中调用了

#Handler.java
/**
     * Use the provided {@link Looper} instead of the default one and take a callback
     * interface in which to handle messages.  Also set whether the handler
     * should be asynchronous.
     *
     * Handlers are synchronous by default unless this constructor is used to make
     * one that is strictly asynchronous.
     *
     * Asynchronous messages represent interrupts or events that do not require global ordering
     * with respect to synchronous messages.  Asynchronous messages are not subject to
     * the synchronization barriers introduced by conditions such as display vsync.
     *
     * @param looper The looper, must not be null.
     * @param callback The callback interface in which to handle messages, or null.
     * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
     * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
     *
     * @hide
     */
    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

可以看到限制了不能直接调用这个Hanlder构造方法设置mAsynchronous属性。mAsynchronousenqueueMessage的时候将会设置到对应的Message
那么mAsynchronous的作用是什么呢?消息循环时通过MessageQueue#next获取下一个消息的。

MessageQueue.java
Message next() {
	...
	//msg.target是对应的Hanlder。这里为null说明是消息屏障,通过MessageQueue#postSyncBarrier方法添加的。
	//可以看到,一旦添加了消息屏障,那么后面的同步消息将会全部被过滤。
	if (msg != null && msg.target == null) {
		do {
			prevMsg = msg;
			msg = msg.next;
		} while (msg != null && !msg.isAsynchronous());
	...
}

这个消息屏障是什么时候添加的呢?经过源码翻阅是scheduleTraversals的时候会添加一个消息屏障。unscheduleTraversals会移除消息屏障。安卓在发送UI更新的消息时,都会通过Messaged#setAsynchronous设置为异步消息。安卓系统这里的设计是为了保证UI绘制相关的操作能够优先执行。

#ViewRootImpl.java
void scheduleTraversals() {
	if (!mTraversalScheduled) {
		mTraversalScheduled = true;
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        mChoreographer.postCallback(
			Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }
}
void unscheduleTraversals() {
	if (mTraversalScheduled) {
		mTraversalScheduled = false;
		mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
		mChoreographer.removeCallbacks(
		Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
	}
}
#MessageQueue.java
/**
     * Posts a synchronization barrier to the Looper's message queue.
     *
     * Message processing occurs as usual until the message queue encounters the
     * synchronization barrier that has been posted.  When the barrier is encountered,
     * later synchronous messages in the queue are stalled (prevented from being executed)
     * until the barrier is released by calling {@link #removeSyncBarrier} and specifying
     * the token that identifies the synchronization barrier.
     *
     * This method is used to immediately postpone execution of all subsequently posted
     * synchronous messages until a condition is met that releases the barrier.
     * Asynchronous messages (see {@link Message#isAsynchronous} are exempt from the barrier
     * and continue to be processed as usual.
     *
     * This call must be always matched by a call to {@link #removeSyncBarrier} with
     * the same token to ensure that the message queue resumes normal operation.
     * Otherwise the application will probably hang!
     *
     * @return A token that uniquely identifies the barrier.  This token must be
     * passed to {@link #removeSyncBarrier} to release the barrier.
     *
     * @hide
     */
    public int postSyncBarrier() {
        return postSyncBarrier(SystemClock.uptimeMillis());
    }

注意

这个接口创建的Handler,假如是在Looper#getMainLooper上。由于所有发送的消息默认是异步消息,会在UI绘制时优先执行,应该确认时必须优先执行的操作才使用此Handler

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值