View 的绘制流程是 measure -> layout -> draw,这个大家都非常熟悉。接下来带领大家来分析下源码(基于SDK 30)
既然开始说到了 View 的绘制流程,那这个流程是什么时候触发的呢?
其实是在ActivityThread.handleResumeActivity中开始的。
这里会调用wm.addView 来添加 DecorView,其中wm 是 WindowManagerImpl
WindowManagerImpl.addView 到 WindowManagerGlobal.addView 到 ViewRootImpl.setView 到 ViewRootImpl.requestLayout 就触发了第一次 View 的绘制,在这个过程中也创建了ViewRootImpl。
接下来从AppCompatActivity的setContentView开始看起
其中这里的getDelegate返回的是AppCompatDelegateImpl,所以又走到如下一步
其中ensureSubDecor是创建DecorView,然后就是根据resId调用inflate方法创建View,接下来分析下LayoutInflate.inflate流程
重点在createViewFromTag方法里
这里可以看下如上两个方法:
- tryCreateView
这里的mFactory、mFactory2、mPrivateFactory都是可以赋值的,其实这个是系统留给我们的 hook View 创建流程的接口,如果没有设置,就走到默认的创建 View 的方法 - onCreateView
这个是真正创建view的方法,以上也会调用到这里
核心就是这块代码,通过反射的方式调用View的构造函数,创建View,自此LayoutInflate.inflate流程结束。
接下来分析下View是如何重新绘制的,牵扯到两个重要方法requestLayout 和 invalidate。
- requestLayout 流程
这里会一层层调用parent的requestLayout,因为DecorView是整个View的最顶层,ViewRootImpl 又是 DecorView 的 parent,所以最终调用到 ViewRootImpl 的 requestLayout。
其中checkThread是检测当前线程是否和view线程一致的判断,重点是scheduleTraversals
performTraversals方法里开启绘制,会逐步调用performMeasure、performLayout、performDraw自此完成绘制流程
这里为调用onMeasure需要的条件( flag 被设置为 PFLAG_DIRTY_OPAQUE),onMeasure调用完成会把flag设置为PFLAG_LAYOUT_REQUIRED
这里为调用onLayout需要的条件(位置有变化,或者设置了 PFLAG_LAYOUT_REQUIRED)
draw会调用到这里, 并且只会重绘 flag 为 dirty 的区域
所以requestLayout 和 invalidate 都会触发整个绘制流程,但是requestLayout 只会触发 measure 和 layout,invalidate 只会触发 draw。
上面就是我对View绘制流程的个人见解,如有不对,欢迎指教;下一篇我们来分析下View的事件分发机制。