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)

相关文章
|
Linux Perl
Linux命令教程:使用cat命令查看和处理文件
Linux命令教程:使用cat命令查看和处理文件
1516 0
|
安全 程序员 Linux
删库跑路?掌握rm命令的技巧,高效删除文件和目录!
删库跑路?掌握rm命令的技巧,高效删除文件和目录!
1387 0
|
XML 编解码 算法
Android开发音效中录制WAV音频和录制MP3音频的讲解及实战(超详细 附源码)
Android开发音效中录制WAV音频和录制MP3音频的讲解及实战(超详细 附源码)
668 0
|
Java 调度 Android开发
Android面试题之Kotlin中async 和 await实现并发的原理和面试总结
本文首发于公众号“AntDream”,详细解析了Kotlin协程中`async`与`await`的原理及其非阻塞特性,并提供了相关面试题及答案。协程作为轻量级线程,由Kotlin运行时库管理,`async`用于启动协程并返回`Deferred`对象,`await`则用于等待该对象完成并获取结果。文章还探讨了协程与传统线程的区别,并展示了如何取消协程任务及正确释放资源。
484 0
|
关系型数据库 MySQL OLTP
性能工具之 MySQL OLTP Sysbench BenchMark 测试示例
【8月更文挑战第6天】使用 pt-query-digest 工具分析 MySQL 慢日志性能工具之 MySQL OLTP Sysbench BenchMark 测试示例
1001 0
性能工具之 MySQL OLTP Sysbench BenchMark 测试示例
|
Android开发
android.app.BackgroundServiceStartNotAllowedException
android.app.BackgroundServiceStartNotAllowedException
612 3
|
Kotlin
Kotlin中的When表达式:灵活、强大且直观的条件控制工具
Kotlin中的When表达式:灵活、强大且直观的条件控制工具
462 0
|
Android开发
ImageView设置tint ,修改图标颜色
ImageView设置tint ,修改图标颜色
|
安全 网络安全 API
163邮箱imap服务器怎么填写
163邮箱imap服务器怎么填写
|
安全 网络安全
[网络安全]upload-labs Pass-19 解题详析
[网络安全]upload-labs Pass-19 解题详析
501 0