android view requestLayout,invalidate 事件的分发,接收,以及处理

handleResumeActivity

DecorView 是在ActivityThread 中的handleResumeActivity 通过mWindowManager 挂到 ViewRootImpl()上面去的。

所以所有的 view 的 requestLayout(),invalidate(),

都是通过 自身的parent.invalidate(),一步一步传递到最顶层的 DecorView,然后最后传递到ViewRootImpl里面。

这个事App process中的windowmanager中的一个成员变量

猜测应该是 每个acitivity 或者dialog都是一个window 要注册到这个里面去。

WindowManagerImpl 也变成了本地的代理。

在WindowManagerGlobal中 维护了这样一个 rootview 窗口的队列
private final ArrayList mViews = new ArrayList();
时刻保证 哪个窗口在最前面,点击事件传给谁。

他通过 openSession(),将自己和远端service绑定起来

WindowManagerGlobal 中


    public void addView(View view, ViewGroup.LayoutParams params,

。。。。。

//rootImpl
            root.setView(view, wparams, panelParentView);
。。。。

}

ViewRootImpl.java

public void setView()

//通过rootImpl                     res = //mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel);

这样子直接挂到了 windowmanagerService 上面注册,准备接受事件用,
什么touch事件啊 之类的都是通过windowmanagersetvice 中持有这个window的token 进行下发的。

扯远了 继续看 requestLayout();

在ViewRootImpl 中,

   @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
    void invalidate() {
        mDirty.set(0, 0, mWidth, mHeight);
        if (!mWillDrawSoon) {
            scheduleTraversals();
        }
    }

可以看到 不管是request 还是invalidate 都会 调用相同的代码scheduleTraversals();我们可以这么理解,就是说 layout和重绘都是在一次绘制过程中完成的,而不是两次。

在简单点描述就是 你在代码里面 前面请求requestLayout(),并且也请求了invalidate(),并不会产生两次 重绘。

在简单点来说,在一个msg循环里面,你多次请求requestLayout(),都是会被系统合并的。

    void scheduleTraversals() {
//如果已经在 重绘的过程中,这个请求会被忽略掉的。
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
//这个东西很厉害的,在messageQuene中会设置栅栏,涉及到垂直同步的问题。
            mTraversalBarrier = mHandler.getLooper().postSyncBarrier();

//在mChoreographer会发出一个sync 的信号。
//并且在下个消息循环的时候 做doTraversal(),准备开始重新layout
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
        }
    }

它会在整个消息循环中加设一个栅栏,在接触此栅栏之前,后面的消息绝对不可能执行,其实就是为了,腾出cpu来 做layout draw事件

    int enqueueSyncBarrier(long when) {
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值