系列文章目录:
- Android性能优化典范综述
- Android性能优化典范之Render Performance
- Android性能优化典范之Understanding Overdraw
- Android性能优化典范之Understanding VSYNC
- Android性能优化典范之Profile GPU Rendering
技术复核(2026-10-13):本文保留 2015 年的视频摘录和示意图。过度绘制的概念仍然适用;下文补充默认颜色表的版本依据、透明混合的例外和删除背景的前提,不把颜色变浅直接当成性能收益。
当时的视频简介:
One of the most problematic performance problems on Android is the easiest to create; thankfully, it’s also easy to fix.
OVERDRAW is a term used to describe how many times a pixel has been re-drawn in a single frame of rendering. It’s a troublesome issue, because in most cases, pixels that are overdrawn do not end up contributing to the final rendered image. As such, it amounts to wasted work for your GPU and CPU.
Fixing overdraw has everything to do with using the available on-device tools, like Show GPU Overdraw, and then adjusting your view hierarchy in order to reduce areas where it may be occurring.
OverDraw概念
视频开头作者举了一个例子,说如果你是一个粉刷匠,你应该会知道,给墙壁粉刷是一件工作量非常大的工作,而且如果你需要重新粉刷一遍的话(比如对颜色不满意),那么第一次的粉刷就白干了. 同样的道理,如果一个不透明区域完全覆盖了前面画出的内容,前面的部分绘制就可能没有贡献。如果你想兼顾高性能和完美的设计,那么你的程序可能会出现一个性能问题:OverDraw!
Overdraw(过度绘制) 指同一帧里,同一个像素被重复绘制。例如下面重叠的卡片,不透明卡片下面被完全遮住的部分可能做了无用功;但不能把“发生重叠”一律视为浪费。半透明内容、阴影和抗锯齿边缘仍需要底下的颜色参与混合,直接删掉底层会改变画面。实际工作量也受裁剪和渲染器优化影响。官方概念说明
过度绘制与 View 的 inflate、measure、layout 不是同一个指标。复杂层级可能增加 CPU 工作,但一个不画背景的父容器不一定增加像素覆盖次数;Compose 的重组次数也不能换算成 overdraw 次数。

这些叠放的布局是一把双刃剑:画面好看了,重复绘制也可能多了。优化时先找不影响外观的冗余绘制,再通过测量判断它是不是当前瓶颈。

追踪OverDraw
在开发者选项中查找 Debug GPU Overdraw / 调试 GPU 过度绘制,选择显示过度绘制区域;旧版截图叫 Show GPU Overdraw。菜单名称和是否提供该选项随系统、厂商而变。它主要帮助观察 HWUI 覆盖的绘制路径,不能当作所有独立 Surface 或自建 OpenGL/Vulkan 渲染的完整计数器。

下面是默认配色中“额外绘制次数”和“总绘制次数”的对应关系;可对照 Android 4.4.4 OpenGLRenderer 与 Caches。颜色覆盖在原画面上,所以最终色调也受原底色影响:
- 蓝色: 1倍过度绘制,即一个像素点绘制了2次
- 绿色:2倍过度绘制,即一个像素点绘制了3次
- 浅红色:3倍过度绘制,即一个像素点绘制了4次
- 深红色:4倍过度绘制及以上,即一个像素点绘制了5次及以上

原色表示没有额外的调试着色,不能据此声称 GPU 没做工作。Android 16 的 SkiaPipeline 仍保留默认蓝/绿/浅红/深红映射,并另有适配色觉的配色;它通过额外重放绘制命令生成计数图,不是读取 GPU 硬件实际执行了多少次着色。
在画面相同的前提下,减少大片不必要的红色区域有助于缩小排查范围。但蓝色不是必须追求的标准,红色也不直接证明掉帧;透明效果可能合理需要多次绘制。

OverDraw的根源
视图重叠中的一个常见浪费是不必要的背景重叠。

如果 Window、根布局、子布局等都画了同色背景,就可能重复覆盖大块区域。下面的旧图展示了删除冗余背景后,大片绿色、红色区域减少的效果;右图的文字和图片附近仍有覆盖色,不能称为“完全没有过度绘制”,也没有据此测得的帧时间收益。

原文使用下面的调用,把 Window 背景替换为透明颜色 Drawable:
1 | getWindow().setBackgroundDrawableResource(android.R.color.transparent); |
这不等于移除了 Drawable,也不是通用优化开关。先在 Layout Inspector 中确认是谁画了背景。通常可以保留一个负责整页底色的背景,只删除重复且没有视觉作用的背景;不要同时把所有底色都删掉。
如果内容在所有相关状态下都完整、不透明地覆盖 Window 原本的背景区域,可以在 Activity 中评估去掉 Window 背景本身。Window.setBackgroundDrawable 从 API 1 就提供:
1 | // Activity 内:仅在内容已完整、不透明地覆盖背景区域时使用。 |
null 不是“透明窗口”的设置;它与透明 ColorDrawable 的行为不同。Window API 合同。需要检查首帧、加载/空内容、页面切换、尺寸变化以及系统栏附近的区域,确认没有露底、变色或闪烁。Android 12 / API 31+ 的启动画面另有 SplashScreen 配置,不能靠运行中的这行调用替代启动主题。
最后关闭 overdraw 着色等调试覆盖层,在相同设备和操作场景下重新采集。Android 12 / API 31+ 可以用 Perfetto FrameTimeline 对比错过期限的帧,再结合实际采集到的线程、GPU 和 SurfaceFlinger 证据;旧系统则按可用 trace 分析。应用背景画得更少,并不自动意味着 SurfaceFlinger 合成耗时也变少。
Perf Matters
keep calm, profile your code, and always remember, Perf Matters
附录
关于过度绘制及其优化,我博客有两篇文章专门介绍:
关于我 && 博客
下面是个人的介绍和相关的链接,期望与同行的各位多多交流,三人行,则必有我师!
- 博主个人介绍 :里面有个人的微信和微信群链接。
- 本博客内容导航 :个人博客内容的一个导航。
- 个人整理和搜集的优秀博客文章 - Android 性能优化必知必会 :欢迎大家自荐和推荐 (微信私聊即可)
- Android性能优化知识星球:付费社群已于 2026 年停止运营,不再招收新成员;此处保留历史介绍。
一个人可以走的更快 , 一群人可以走的更远
