View调用 invalidate() 或 postInvalidate() 刷新UI界面,对应android 8.0
先介绍通知刷新的重要变量ViewParent mParent及其赋值过程,再介绍刷新流程
1. 首先看一张图:
ViewGroup和ViewRootImpl 实现了接口ViewParent
可以看到View 有变量 ViewParent mParent , 所有继承 View 的 子类都有 mParent
每个View或ViewGroup的mParent 指向包含自身的父类ViewGroup
而顶层 DecorView(大部分)的mParent 则指向 ViewRootImpl
2. 接下来是View或ViewGroup如何关联到对应的ViewParent mParent
frameworks/base/core/java/android/view/View.java
其内部函数 assignParent:
frameworks/base/core/java/android/view/ViewGroup.java
addView --> addViewInner --> assignParent
所以在调用 ViewGroup的addView时,会绑定ViewParent mParent
3. 顶层DecorView如何关联到ViewRootImpl
frameworks/base/core/java/com/android/internal/policy/DecorView.java
frameworks/base/core/java/android/view/ViewRootImpl.java
setView函数的第一个参数就是DecorView(大部分都是),这个函数调用参考WindowManagerGlobal.addView()
4.View通知刷新流程
frameworks/base/core/java/android/view/View.java
invalidate() --> invalidate(true) --> invalidateInternal() --> invalidateChild()
frameworks/base/core/java/android/view/ViewGroup.java
invalidateChild -->invalidateChildInParent(ViewGroup)
-->invalidateChildInParent(FrameLayout)
-->invalidateChildInParent(DecorView)
--> invalidateChildInParent(ViewRootImpl)
从最底层View一路传递到顶层的DecorView,最终调用ViewRootImpl的 invalidateChildInParent函数
frameworks/base/core/java/android/view/ViewRootImpl.java
invalidateChildInParent() --> invalidateRectOnScreen() --> scheduleTraversals ()--> TraversalRunnable --> doTraversal() --> performTraversals()
performTraversals函数开始界面刷新。
5.非UI线程调用postInvalidate刷新,实质是往UI线程发送刷新消息,ViewRootImpl中ViewRootHandler绑定的就是主线程
frameworks/base/core/java/android/view/View.java
postInvalidate --> postInvalidateDelayed --> dispatchInvalidateDelayed
frameworks/base/core/java/android/view/ViewRootImpl.java
最终还是调用 View.invalidate , 不过此时已经切换到UI线程
网友评论