最近在撸Golang有点上火了,来整理下安卓源码资料
分析结果基于Audroid API 26
requestLayout()源码分析假如在一个页面上有个按钮,点击按钮就对一个 view.requestLayout(),这个 view 执行的方法如下:InvalidateTextView------onMeasure
InvalidateTextView------onMeasure
InvalidateTextView-------layout
InvalidateTextView--------onLayout
InvalidateTextView----------draw
InvalidateTextView------------onDrawview.requestLayout() 方法的详情@CallSuper
public void requestLayout() { // 清除绘制的缓存
if (mMeasureCache != null) mMeasureCache.clear(); if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) { //只有在布局逻辑中触发请求,如果这是请求它的视图,而不是其父层次结构中的视图
ViewRootImpl viewRoot = getViewRootImpl(); //如果连续请求两次,其中一次自动返回!
if (viewRoot != null && viewRoot.isInLayout()) { if (!viewRoot.requestLayoutDuringLayout(this)) { return;
}
}
mAttachInfo.mViewRequestingLayout = this;
} //todo 为当前view设置标记位 PFLAG_FORCE_LAYOUT
mPrivateFlags |= PFLAG_FORCE_LAYOUT;
mPrivateFlags |= PFLAG_INVALIDATED; if (mParent != null && !mParent.isLayoutRequested()) { // todo 向父容器请求布局 这里是向父容器请求布局,即调用父容器的requestLayout方法,为父容器添加PFLAG_FORCE_LAYOUT标记位,而父容器又会调用它的父容器的requestLayout方法,即requestLayout事件层层向上传递,直到DecorView,即根View,而根View又会传递给ViewRootImpl,也即是说子View的requestLayout事件,最终会被ViewRootImpl接收并得到处理
mParent.requestLayout();
} if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
mAttachInfo.mViewRequestingLayout = null;
}
}1、如果缓存不为null,清除绘制的缓存if (mMeasureCache != null) mMeasureCache.clear();2、这里判断了是否在layout,如果是,就返回,也就可以理解为: 如果连续请求两次