Android Barrier

本文深入探讨了Android中Barrier的概念及其在布局和绘制过程中的作用,解释了如何通过Barrier来管理消息队列,确保UI绘制的流畅性和效率。文章详细说明了Barrier如何在ViewRootImpl开始measure和layoutViewTree时向主线程的Handler添加,以及如何通过创建Handler或发送Message来设置异步消息,避免影响UI绘制。

为了让View能够有快速的布局和绘制,android中定义了一个Barrier的概念,当View在绘制和布局时会向Looper中添加了Barrier(监控器),这样后续的消息队列中的同步的消息将不会被执行,以免会影响到UI绘制,但是只有异步消息才能被执行。 所谓的异步消息也只是体现在这,添加了Barrier后,消息还可以继续被执行,不会被推迟运行。 如何使用异步消息,只有在创建Handler(构造方法的参数上标识是否异步消息)的时候或者在发送Message(Mesasge#setAsynchronous(true))时进行设置。而异步消息应用层是无法设置,因为相关设置的方法均是Hide的。


两种方式可以发送异步消息

1.在创建Handler时,在构造方法上传递参数true就可以,如下:

public Handler(Callback callback, boolean async) {
        ...
        mAsynchronous = async;
    }
在Handler上设置异步的话,那么使用此Handler发送的消息都将被设置Mesasge#setAsynchronous(true)

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
Message#setAsynchronous去设置,但是也是Hide的。 
/**
     * Sets whether the message is asynchronous.
     *
     * Asynchronous messages represent interrupts or events that do not require global ordering
     * with represent to synchronous messages.  Asynchronous messages are not subject to
     * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
     *
     * @param async True if the message is asynchronous.
     *
     * @see #isAsynchronous()
     * @see MessageQueue#enqueueSyncBarrier(long)
     * @see MessageQueue#removeSyncBarrier(int)
     *
     * @hide
     */
    public void setAsynchronous(boolean async) {
        if (async) {
            flags |= FLAG_ASYNCHRONOUS;
        } else {
            flags &= ~FLAG_ASYNCHRONOUS;
        }
    }

当ViewRootImpl开始measure和layout ViewTree时,会向主线程的Handler添加Barrier

void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            scheduleConsumeBatchedInput();
        }
    }
void unscheduleTraversals() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);
            mChoreographer.removeCallbacks(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        }


scheduleTraversals()方法都会在requestLayout时会被调用,所有导致布局变化的对会触发。例如:ViewGroup#addView,removeView或者View 从VISIBLE-->GONE,或者GONE-->VISIBLE等。




Android 中,如果你想要实现类似 **Barrier(屏障)** 的功能来控制多个控件的布局行为,尤其是在 `ConstraintLayout` 中,可以使用 `Barrier` 组件。它是 `ConstraintLayout` 提供的一个虚拟辅助视图,用于将一组控件作为一个整体来控制它们的布局位置。 ### 示例:使用 Barrier 控制多个控件 ```xml <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文本1" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文本2" app:layout_constraintLeft_toRightOf="@id/textView1" app:layout_constraintTop_toTopOf="parent" /> <!-- 创建一个 Barrier --> <androidx.constraintlayout.widget.Barrier android:id="@+id/barrier" android:layout_width="wrap_content" android:layout_height="wrap_content" app:barrierDirection="right" <!-- 方向:右侧 --> app:constraint_referenced_ids="textView1,textView2" /> <!-- 引用的控件 --> <!-- 受 Barrier 控制的控件 --> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮" app:layout_constraintLeft_toRightOf="@id/barrier" app:layout_constraintTop_toBottomOf="@id/textView1" /> </androidx.constraintlayout.widget.ConstraintLayout> ``` ### Barrier 的作用 - **动态对齐**:Barrier 的位置会根据其引用的多个控件中“最边缘”的那个自动调整。 - **统一控制布局流**:你可以让其他控件相对于 Barrier 进行约束,而不是直接依赖多个控件。 --- ### 使用 Barrier 的常见场景 - 多个控件宽度不固定时,希望后续控件统一排列在它们之后。 - 实现类似“标题组”之后的内容对齐。 - 动态隐藏/显示多个控件后,布局仍能自适应。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值