View 的 requestLayout 发起的重绘流程源码分析(Android Q)
我们平时经常会调用 View 类的 requestLayout 方法更新视图,那么它又是如何发起的重绘逻辑呢?
View 的 requestLayout 方法:
public void requestLayout() {
……
if (mParent != null && !mParent.isLayoutRequested()) {
//调用父视图的 requestLayout 方法
mParent.requestLayout();
}
……
}
该方法进行了一些属性设置,接下来调用了父视图的 requestLayout 方法。该方法一直会顺着视图树向上调用,一直到根视图,也就是 DecorView。但最终是调用到 DecorView 的 requestLayout 方法吗?
我们先来看 mParent 在什么地方赋值的?
View 的 assignParent 方法
protected ViewParent mParent;
void assignParent(ViewParent parent) {
if (mParent == null) {
mParent = parent;
} else if (parent == null) {
mParent = null;
} else {
throw new RuntimeException("view " + this + " being added, but"
+ " it already has a parent");
}
}
mParent 是通过 assignParent 的参数设置的,又是谁调用了 assignParent 方法呢?
ViewRootImpl 的 setView 方法:
我们回一下,ViewRootImpl 的 setView 方法是在 DecorView 要添加到 Window 时调用的。
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView){
……
view.assignParent(this);
……
}
其实是在 ViewRootImpl 的 setView 方法中,调用了 View 的 assignParent 方法,参数呢,就是 ViewRootImpl 对象。也就是说 DecorView 的 mParent 是 ViewRootImpl 对象。
所以,View 的 requestLayout 方法,最终通过它的 mParent 逐级冒泡,最终调用到 ViewRootImpl 中的 requestLayout 方法。这不就和本文前半部分的内容接上了吗,这两种视图显示过程,都是通过 ViewRootImpl 中的 requestLayout 方法发起的。
总结
View 类的 requestLayout 方法更新视图,是如何发起的重绘逻辑呢?
-
ViewRootImpl 的 setView 方法中,调用了 View 的 assignParent 方法,参数呢,就是 ViewRootImpl 对象。也就是说 DecorView 的 mParent 是 ViewRootImpl 对象。
-
View 的 requestLayout 方法,最终通过它的 mParent 逐级冒泡,最终调用到 ViewRootImpl 中的 requestLayout 方法。所以本质上来讲,它是通过 ViewRootImpl 中的 requestLayout 方法发起的。
PS:更多分析文章,请查看系列文章–>《Android底层原理解析》
PS:更多分析文章,请查看系列文章–>《Android底层原理解析》
PS:更多分析文章,请查看系列文章–>《Android底层原理解析》