Android invalidate、postInvalidate、requestLayout的区别

一、方法介绍

1、invalidate():

invalidate方法用于在UI线程中请求重绘视图。当我们希望在主线程中更新UI时,可以在UI线程中直接调用invalidate()方法。

内部实现:调用了invalidate方法后,为该View添加一个标记位,同时不断向父容器请求刷新,父容器通过计算得出自身需要重绘的区域,直到传递到ViewRootImpl中,最终触发performTraversals方法,开始View树重绘流程(只绘制需要重绘的视图)

2、postInvalidate():

postInvalidate方法用于在非UI线程中请求重绘视图。如果我们希望在非UI线程中更新UI,就需要使用postInvalidate()方法。

内部实现:当调用postInvalidate()方法时,系统会通过Handler将重绘任务添加到主线程的消息队列中。在UI线程的消息循环中,当处理到该消息时,会触发invalidate()方法来进行实际的重绘操作。这样可以确保在非UI线程中请求的重绘操作在主线程中执行,避免多线程并发导致的问题。

3、requestLayout():

requestLayout方法用于请求重新布局视图。当我们希望更新视图的尺寸或位置时,需要调用requestLayout()方法。该方法会触发视图层次结构的重新测量、布局和绘制过程。例如,当修改了视图的宽度、高度、位置或其他布局参数时,应调用requestLayout()方法来请求重新布局。

内部实现:调用requestLayout方法,标记当前View及父容器,requestLayout()事件逐层向上传递,直到DecorView,DecorView传递给ViewRootImpl,ViewRootImpl#requestLayout()接收并处理该事件【最终走到这个方法ViewRootImpl.scheduleTraversals()】。ViewRootImpl会调用三大流程,从measure开始,对于每一个含有标记位的view及其子View进行测量onMeasure、布局onLayout、绘制onDraw。

二、相同点

都是用来更新Android视图的方法

三、不同点

1、invalidate方法用于在主线程中请求重绘视图,postInvalidate方法可以再非UI线程中调用

2、invalidate和postInvalidate方法只会触发onDraw方法,requestLayout会触发onMeasure和onLayout方法,当view的位置发生改变才会执行onDraw方法,因此如果要使当前view重绘需要调用invalidate。

疑问 :
requestLayout()何时不会触发onDraw()?

如果没有改变控件的left\right\top\bottom就不会触发onDraw()
invalidate()在什么情况下不会触发onDraw?

在ViewGroup中,invalidate默认不重新绘制子view。
如何让ViewGroup在invalidate时会触发onDraw?

本质需要将ViewGroup的dirtyOpaque设置为false

1.在构造函数中调用setWillNotDraw(false);

2.给ViewGroup设置背景。调用setBackground。

相关推荐
百锦再5 小时前
Android Studio开发中Application和Activity生命周期详解
android·java·ide·app·gradle·android studio·studio
移动开发者1号5 小时前
Android现代进度条替代方案
android·app
万户猴5 小时前
【Android蓝牙开发实战-11】蓝牙BLE多连接机制全解析1
android·蓝牙
RichardLai885 小时前
[Flutter 基础] - Flutter基础组件 - Icon
android·flutter
前行的小黑炭5 小时前
Android LiveData源码分析:为什么他刷新数据比Handler好,能更节省资源,解决内存泄漏的隐患;
android·kotlin·android jetpack
清霜之辰6 小时前
安卓 Compose 相对传统 View 的优势
android·内存·性能·compose
_祝你今天愉快6 小时前
再看!NDK交叉编译动态库并在Android中调用
android
一杯凉白开6 小时前
Android View 事件的分发机制 四句口诀 先问拦截再派送,子不处理父兜底, 一旦消费无后续, 滑动冲突靠逻辑。
android
冬田里的一把火36 小时前
[Android]导航栏中插入电源菜单
android
星途码客6 小时前
SQLyog中DELIMITER执行存储过程时出现的前置缩进问题
android