Skip to content
阅读进度

invalidate、requestLayout、postInvalidate 有什么区别? ​

返回 View 与显示链路 目录

标准回答 ​

invalidate 表示当前显示内容需要更新,主要触发后续绘制;requestLayout 表示布局需求变了,请框架重新评估测量和位置;postInvalidate 允许把重绘请求投递到 UI 线程,适用于规定的跨线程通知场景。

比如自定义进度条只改变进度颜色或填充长度,外部宽高不变,通常调用 invalidate。字体或内容变化导致控件需要更大空间,则应考虑 requestLayout;如果内容也改变,自定义 setter 还要正确通知绘制更新。

它们都不是“现在立刻把整棵树重新画完”。框架会合并更新,并根据脏状态、约束和缓存决定实际需要执行哪些阶段。也不能把 requestLayout 理解为每个节点必定完整重做三步,或把 invalidate 理解为永远只改几个像素、没有其他成本。

关键机制 ​

  • 普通 invalidate 应在 UI 线程调用;postInvalidate 是投递更新请求,不是让 onDraw 在后台执行。
  • postInvalidateOnAnimation 将更新与动画帧节奏对齐;它仍不保证某个固定时刻已经展示。
  • 系统控件的 setter 往往已包含必要更新;业务不要无条件重复 requestLayout 制造额外工作。

通俗例子 ​

主线程把仪表盘进度从 20 改成 30,再 invalidate;如果还把仪表盘半径需求改大,则连测量需求也改变了。

追问与回答 ​

连续调用十次 invalidate,会立刻画十次吗? ​

不一定。短时间内的无效化请求可以被合并到后续遍历,框架主要保证最终状态在合适时机更新,不保证每个中间状态都单独形成一帧。如果业务必须按顺序呈现多个状态,应使用帧驱动的动画或状态控制,而不是依靠连着调用 invalidate。

易混淆点 ​

后台调用 postInvalidate 不会自动让你此前对 View 或共享数据的任意修改变得线程安全。

参考资料 ​

内容来源 ​

用完整回答理解机制,用真实证据解释项目。