跳到主要内容

渲染性能优化

问题

如何保证 Android 应用流畅的 60fps 渲染?常见的掉帧原因有哪些?

答案

渲染流水线

Android 的渲染目标是 60fps,即每帧必须在 16.67ms 内完成。

常见卡顿原因

原因说明解决方案
布局层级过深多层嵌套 LinearLayout使用 ConstraintLayout 扁平化
过度绘制同一像素被绘制多次移除不必要的背景色
主线程耗时操作IO/网络/复杂计算移到子线程/协程
invalidate() 频繁调用不必要的重绘使用局部更新
RecyclerView 未优化列表滑动卡顿ViewHolder 复用、预加载

过度绘制检测

开发者选项 → 调试 GPU 过度绘制:

颜色过度绘制次数说明
无色0绘制 1 次(正常)
蓝色1绘制 2 次(可接受)
绿色2绘制 3 次(需关注)
粉色3绘制 4 次(需优化)
红色4+绘制 5 次以上(必须优化)

优化手段

// 1. 使用 ConstraintLayout 减少层级
// ❌ 3 层嵌套
LinearLayout
└── LinearLayout
└── LinearLayout

// ✅ 1 层
ConstraintLayout

// 2. 移除不必要的背景
// ❌ Activity 和根布局都设了白色背景
// ✅ 在 Activity 的 theme 中去掉 windowBackground
<style name="AppTheme" parent="Theme.Material3.DayNight">
<item name="android:windowBackground">@null</item>
</style>

// 3. ViewStub 延迟加载
// 不经常显示的布局使用 ViewStub
<ViewStub
android:id="@+id/error_stub"
android:layout="@layout/error_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

使用 Systrace / Perfetto 分析

# 抓取 trace
python systrace.py -o trace.html gfx view wm am

# 或使用 Perfetto(推荐)
adb shell perfetto -o /data/misc/perfetto-traces/trace.pb -t 10s -b 32mb \
sched freq idle am wm gfx view

常见面试问题

Q1: 如何判断掉帧的原因?

答案

  1. Systrace / Perfetto:查看是否有超过 16ms 的帧,分析 Choreographer 的 doFrame 耗时
  2. GPU Profiling:开发者选项 → GPU 呈现模式分析,查看绿色线以上的条形图
  3. StrictMode:检测主线程 IO 操作

Q2: Compose 和传统 View 的渲染性能差异?

答案

  • Compose 跳过了 XML 解析和 inflate 过程,使用编译时代码生成
  • Compose 的智能重组只重绘变化部分
  • 但 Compose 在 debug 模式下性能明显差于 release,测试性能必须用 release 版本
  • 对于复杂的列表场景,Compose LazyColumn 和 RecyclerView 性能基本持平

相关链接