View#invalidate是如何调用当前View#onDraw方法的?

简介: View#invalidate是如何调用当前View#onDraw方法的?

View#invalidate后,一定会调用当前child的onDraw。这个方法跟 requestLayout 的区别在于,它不一定会触发 View 的 measurelayout 的操作,多数情况下只会执行 draw 操作。

我们从View#invalidate开始,追一下调用流程。

1、View#invalidate:让当前的整个View无效。如果view可见,onDraw方法将在随后的某个节点调用。


/**

* Invalidate the whole view. If the view is visible,

* {@link #onDraw(android.graphics.Canvas)} will be called at some point in

* the future.

* <p>

* This must be called from a UI thread. To call from a non-UI thread, call

* {@link #postInvalidate()}.

*/

public void invalidate() {

invalidate(true);

}

2、View#invalidate(boolean invalidateCache):如果dimensions和content都相同,那么就可以跳过将drawing cache置为无效的步骤。


/**

* This is where the invalidate() work actually happens. A full invalidate()

* causes the drawing cache to be invalidated, but this function can be

* called with invalidateCache set to false to skip that invalidation step

* for cases that do not need it (for example, a component that remains at

* the same dimensions with the same content).

*

* @param invalidateCache Whether the drawing cache for this view should be

* invalidated as well. This is usually true for a full

* invalidate, but may be set to false if the View's contents or

* dimensions have not changed.

* @hide

*/

@UnsupportedAppUsage

public void invalidate(boolean invalidateCache) {

invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);

}

3、child调用View#invalidate后,完整的调用流程:


--> View#invalidate

--> View#invalidate(boolean invalidateCache)

--> View#invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate):将Rect区域设置给AttachInfo#mTmpInvalRect

--> ViewGroup#invalidateChild(View child, final Rect dirty):默认开启了硬件加速,AttachInfo#mHardwareAccelerated为true

--> ViewGroup#onDescendantInvalidated(@NonNull View child, @NonNull View target)

--> ViewParent#onDescendantInvalidated(@NonNull View child, @NonNull View target):递归调用所有的parent

...

--> ViewRootImpl#onDescendantInvalidated(@NonNull View child, @NonNull View target)

--> ViewRootImpl#invalidate():

--> ViewRootImpl#scheduleTraversals()

--> ViewRootImpl#TraversalRunnable#run()

--> ViewRootImpl#doTraversal()

--> ViewRootImpl#performTraversals():cancelDraw为false

--> ViewRootImpl#performDraw()

--> ViewRootImpl#draw(boolean fullRedrawNeeded)

--> ThreadedRenderer#draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks):绘制DecorView

--> ThreadedRenderer#updateRootDisplayList(View view, DrawCallbacks callbacks)

--> ThreadedRenderer#updateViewTreeDisplayList(View view):读取PFLAG_INVALIDATED标记并给#View#mRecreateDisplayList赋值,然后清除PFLAG_INVALIDATED标记。

--> View#updateDisplayListIfDirty():用到了mRecreateDisplayList,此时mRecreateDisplayList为true。

--> DecorView#draw(Canvas canvas):

--> View#draw(Canvas canvas)

--> View#dispatchDraw(Canvas canvas)

--> ViewGroup#dispatchDraw(Canvas canvas)

--> ViewGroup#drawChild(Canvas canvas, View child, long drawingTime)

--> View#draw(Canvas canvas, ViewGroup parent, long drawingTime)

--> View#updateDisplayListIfDirty()

--> ViewGroup#dispatchDraw(Canvas canvas)

--> ViewGroup#drawChild(Canvas canvas, View child, long drawingTime)

...

最终调用到child的onDraw。因为在View#draw(Canvas canvas)方法中,会调用View#onDraw(Canvas canvas)

相关文章
|
7月前
|
存储 安全 Android开发
HarmonyOS实战:一招搞定保存图片到相册
本文介绍了在鸿蒙系统中实现保存图片到相册的功能,包括申请权限和使用系统安全控件两种方式。文中详细讲解了如何通过网络请求下载图片并保存为本地文件,以及如何将指定布局生成图片并保存。鸿蒙系统对权限管理较为严格,推荐使用系统提供的安全控件(如 SaveButton)以保护用户隐私,避免手动申请权限。此外,文章还对比了鸿蒙与 Android/iOS 的实现差异,指出鸿蒙在功能实现上更简单,但需注意权限规范以确保项目顺利上线。
980 0
HarmonyOS实战:一招搞定保存图片到相册
|
存储 程序员 调度
[计算机组成原理(唐朔飞 第2版)]第一章 计算机系统概论 & 第二章 计算机的发展及应用(学习复习笔记)
[计算机组成原理(唐朔飞 第2版)]第一章 计算机系统概论 & 第二章 计算机的发展及应用(学习复习笔记)
|
人工智能 自然语言处理 算法
企业内训|AI/大模型/智能体的测评/评估技术-某电信运营商互联网研发中心
本课程是TsingtaoAI专为某电信运营商的互联网研发中心的AI算法工程师设计,已于近日在广州对客户团队完成交付。课程聚焦AI算法工程师在AI、大模型和智能体的测评/评估技术中的关键能力建设,深入探讨如何基于当前先进的AI、大模型与智能体技术,构建符合实际场景需求的科学测评体系。课程内容涵盖大模型及智能体的基础理论、测评集构建、评分标准、自动化与人工测评方法,以及特定垂直场景下的测评实战等方面。
614 4
|
Web App开发 移动开发 前端开发
多种方法实现Loading(加载)动画效果
当我们ajax提交一个按钮的时候,给那个按钮来个Loading效果会高端很多,体验也会上升个层次。 既能让用户知道正在提交中,也能防止二次提交,好处多多呢。
多种方法实现Loading(加载)动画效果
|
Android开发
Android stdio 无法新建或打开AIDL文件(解决方法)
Android stdio 无法新建或打开AIDL文件(解决方法)
1330 0
|
Kotlin
Kotlin中的When表达式:灵活、强大且直观的条件控制工具
Kotlin中的When表达式:灵活、强大且直观的条件控制工具
385 0
|
存储 编译器 C语言
【C++】——string的功能介绍及使用
【C++】——string的功能介绍及使用
288 0
【C++】——string的功能介绍及使用
|
XML Java 测试技术
车载Android应用开发与分析 - SystemUI 「功能」与「源码结构」分析
本期内容开始,我们将介绍原生Android Automotive中车载应用的实现方式和它的原理。首先要介绍的就是车载应用开发中非常重要的一个系统应用,Android系统的UI - SystemUI。
1456 1
车载Android应用开发与分析 - SystemUI 「功能」与「源码结构」分析
|
存储 监控 网络协议
2.1 网络io、io多路复用select/poll/epoll、基于事件驱动的reactor
2.1 网络io、io多路复用select/poll/epoll、基于事件驱动的reactor
270 0