本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点
Android 的渲染显示是一个复杂的过程,涉及多个系统组件和层次。为了理解帧率、掉帧和卡顿的原理,我们需要深入了解 Android 的渲染体系。
Android 的渲染显示原理
1、 应用程序层:
- 应用程序通过调用 Android 的 UI 框架,例如
View
和ViewGroup
,初始化和更新 UI 组件。这些组件最终被绘制在屏幕上。
2、 UI 线程和 View 渲染:
- Android 的 UI 操作通常在主线程(UI 线程)中进行。当需要更新 UI 时,应用程序触发重绘(invalidate)操作,系统将这些操作加入消息队列进行异步处理。
3、 Choreographer:
Choreographer
是一个关键组件,它负责管理帧的生产和消费。它协调应用程序绘制与 VSYNC 信号(垂直同步)的同步,以实现平滑的动画效果。Choreographer
会在 VSYNC 信号到来时触发doFrame
回调,在这个回调中完成布局、测量和绘制等操作。
4、 硬件加速和 OpenGL:
- Android 使用硬件加速(利用 GPU)来提高渲染性能。大多数绘制操作通过 OpenGL 进行硬件加速,减少了 CPU 的负担。
- 渲染命令会被批量地发送到 GPU 进行处理。
5、 SurfaceFlinger 和显示:
SurfaceFlinger
是 Android 的系统服务,负责合成窗口,这意味着它把不同应用的窗口和系统 UI 组合在一起并发送到显示屏上。- 渲染管线的最终结果被交给
SurfaceFlinger
,它合成最终的显示图像帧。
帧率、掉帧和卡顿原理
-
帧率(FPS):指每秒能够渲染的帧数。通常来说,Android 的目标帧率是 60 FPS,由于大多数屏幕的刷新率都是 60Hz。
-
掉帧:发生在一个帧的处理时间超过目标帧间隔(如 16.67ms 用于 60 FPS),导致帧无法按时显示,这样用户会感觉到卡顿。
-
卡顿:连续掉帧会被用户感知为卡顿。应用程序的执行阻塞、昂贵的绘制操作、复杂的布局测量等都可能导致卡顿。
正常帧处理与掉帧检测
我们可以借助 Choreographer
和 Android API 来检测帧率和掉帧。以下是使用 Choreographer
的一个简单示例:
public class FrameCallback implements Choreographer.FrameCallback {
private long lastFrameTimeNanos = 0;
@Override
public void doFrame(long frameTimeNanos) {
if (lastFrameTimeNanos != 0) {
long frameTime = frameTimeNanos - lastFrameTimeNanos;
double frameTimeMs = frameTime / 1_000_000.0;
if (frameTimeMs > 16.67) {
System.out.println("Frame drop detected: Frame time = " + frameTimeMs + "ms");
}
}
lastFrameTimeNanos = frameTimeNanos;
// Continuously post frame callback
Choreographer.getInstance().postFrameCallback(this);
}
}
// To start tracking frames
public void startTrackingFrames() {
Choreographer.getInstance().postFrameCallback(new FrameCallback());
}
其他检测帧率的方法
-
FrameMetrics API(Android 7.0+):提供更加详细的帧时间和过渡信息,适用于开发过程中对性能监控和优化。
-
Android Profiler:Android Studio 提供了强大的性能分析工具,帮助检测和解决性能瓶颈。
-
Systrace:可以使用 Systrace 获取系统和应用的整体性能数据和渲染轨迹。
综上,Android 的渲染体系是高度优化和复杂的,要实现流畅的用户体验,需要关注主线程的性能,尽量减少阻塞,并运用合适的工具进行性能监控和优化。
欢迎关注我的公众号AntDream查看更多精彩文章!