以下是关于 postInvalidateOnAnimation
一、什么是 postInvalidateOnAnimation?
postInvalidateOnAnimation 是 Android View 中用于在下一帧动画刷新时请求重绘界面的方法。
定义:
public void postInvalidateOnAnimation()这是一个非阻塞的、异步的重绘请求,与 invalidate() 类似,但它会在下一帧的动画帧(VSync 信号)到达时触发 UI 刷新,从而提供更高效的 UI 更新。
常用场景:
- 当你需要在动画中重绘 View 时(例如:在
ValueAnimator、ObjectAnimator动画中更新 View 的状态)。 - 使用
Choreographer控制重绘的节奏,避免不必要的重绘。 - 用于提高性能和流畅性,避免不必要的 CPU 开销。
二、postInvalidateOnAnimation 和 invalidate() 的区别
方法 | 触发时间 | 是否异步 | 性能 |
| 立刻刷新 View | 否(同步调用) | UI 可能会多次重绘,增加性能开销 |
| 立刻请求重绘 | 是(异步调用) | 使用消息队列请求重绘,下一帧刷新 |
| 下一帧刷新 | 是(异步调用) | 依赖 VSync 信号,更高效、更节能 |
为什么 postInvalidateOnAnimation 更高效?
postInvalidateOnAnimation依赖于 Choreographer,它与 Android 的 VSync 信号同步,只在 VSync 到来时重绘,节省了 CPU 资源。invalidate()会立即标记 View 需要重绘,但可能被多次调用,导致性能浪费。- 适用于动画驱动的 View 重绘,如进度条、运动的图形、游戏元素等。
三、如何使用 postInvalidateOnAnimation?
使用示例 1:在自定义 View 中手动重绘
public class CustomView extends View {
private float radius = 50f; // 动态半径
private Paint paint;
public CustomView(Context context) {
super(context);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制一个动态变化的圆
canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, paint);
}
public void increaseRadius() {
radius += 10f;
// 下一帧动画时重绘
postInvalidateOnAnimation();
}
}说明:
- 每次调用
increaseRadius(),不会立即重绘,而是在下一帧 VSync 到来时重绘。 - 这种做法比直接调用
invalidate()更高效,避免了 UI 线程的多次重绘。
使用示例 2:结合 ValueAnimator 动画刷新 View
public class AnimatedCircleView extends View {
private float radius = 50f; // 半径
private Paint paint;
public AnimatedCircleView(Context context) {
super(context);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLUE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制一个动态变化的圆
canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, paint);
}
public void startAnimation() {
ValueAnimator animator = ValueAnimator.ofFloat(50f, 200f);
animator.setDuration(2000); // 动画持续 2 秒
animator.addUpdateListener(animation -> {
radius = (float) animation.getAnimatedValue();
postInvalidateOnAnimation(); // 在 VSync 信号到达时重绘
});
animator.start();
}
}说明:
- 在
ValueAnimator的onUpdate回调中,每次动画帧都会调用postInvalidateOnAnimation(),动画流畅不卡顿。 - 这是最常见的与动画配合的重绘方案,与
invalidate()不同,不会造成多次重绘开销。
四、深入理解实现原理
1. VSync(垂直同步)信号
- Android 系统的 VSync 是一种显示刷新同步信号,它的频率通常是 60Hz(每秒 60 帧)。
- VSync 的作用是避免图像撕裂,并控制 UI 更新的节奏。
postInvalidateOnAnimation()会将重绘请求插入到 Choreographer 帧队列 中,等待下一次 VSync 到来。
2. Choreographer 机制
Choreographer是 Android 中的时间调度器,它与 VSync 信号同步。Choreographer负责调用doFrame(long frameTimeNanos),并在每一帧执行 View 的重绘、动画和 UI 事件。postInvalidateOnAnimation()使用的就是Choreographer.postFrameCallback()。
源码简化版:
public void postInvalidateOnAnimation() {
ViewRootImpl viewRoot = getViewRootImpl();
if (viewRoot != null) {
viewRoot.invalidate();
} else {
Choreographer.getInstance().postFrameCallback(new FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
invalidate();
}
});
}
}解释:
- ViewRootImpl.invalidate():如果 View 已经附加到窗口,直接请求 ViewRoot 重绘。
- Choreographer.postFrameCallback():如果 View 没有附加到窗口,则在下一个 VSync 到来时重绘。
五、常见的使用场景
场景 | 为什么使用 postInvalidateOnAnimation |
自定义 View 动画 | 避免 View 在动画中频繁调用 |
游戏中的角色移动 | 在 VSync 信号到来时重绘,减少 GPU 和 CPU 占用 |
高频率动画效果 | 动画逻辑的重绘与 VSync 同步,动画流畅不卡顿 |
圆形进度条/动态加载条 | 保证进度条更新与屏幕刷新同步,避免卡顿 |
六、常见的面试问题
postInvalidateOnAnimation和invalidate的区别?
invalidate()会立刻刷新 View,而postInvalidateOnAnimation()只在 VSync 信号到来时刷新,性能更高,节省资源。
- 为什么要使用 VSync?
- VSync 可以同步显示刷新,防止屏幕撕裂,节省 CPU 和 GPU 开销。
Choreographer是什么?
Choreographer是 Android 中的全局调度器,用于在每一帧中调用 View 重绘、动画和事件回调。
七、简单的博客范文
标题:详解 postInvalidateOnAnimation:高效重绘 View 的利器
前言
在 Android 开发中,invalidate() 是我们常用的请求 View 重绘的方法,但在动画场景中,频繁调用 invalidate() 会导致高 CPU 占用和不流畅的动画。为了更高效地更新 View,Android 提供了**postInvalidateOnAnimation**。
正文
- 什么是
postInvalidateOnAnimation? postInvalidateOnAnimation和invalidate的区别?- 如何使用?(示例)
- 原理解析:VSync 和 Choreographer
- 常见场景:游戏、动画、进度条
如果你希望对博客的内容和结构有更多的调整,请告诉我!我可以为你定制一篇完整的技术博客。 😊

















