一、Android性能优化概述
为什么需要性能优化?
说实话,我刚入行那会儿,也觉得性能优化是“锦上添花”的事。功能跑通了不就行了?直到有一次——
我负责的一个社交App,上线后用户反馈“刷朋友圈卡得像PPT”。后台数据显示,日活用户三天跌了15%。老板拍桌子问我怎么回事。我查了一整天,发现是列表滑动时内存抖动太严重,GC频繁触发,导致掉帧。
嗯,从那以后,我再也不敢小看性能优化了。
你想想看,用户装你的App,不是为了看它有多卡。用户要的是流畅、省电、不闪退。说白了,性能就是用户体验的底线。底线守不住,功能再花哨也没用。
核心观点:性能优化不是“可选项”,而是“必选项”。它直接决定用户留存、App评分、甚至商业收入。
具体来说,为什么需要性能优化?我总结了三点:
- 用户耐心有限——研究表明,App启动超过3秒,53%的用户会直接卸载。你想想看,你开发了几个月的功能,用户连看都不看就走了。
- 设备碎片化严重——Android设备从几百块的入门机到上万块的旗舰机,性能差距巨大。你的App不能只在测试机上跑得顺。
- 竞品太卷——隔壁iOS的App丝般顺滑,你的Android版卡成PPT?用户会怎么想?
性能优化的目标
性能优化的目标,说白了就四个字:又快又稳。
快,是指响应速度。用户点击按钮,App要立刻有反馈。滑动列表,要跟手。启动App,要秒开。
稳,是指不卡顿、不闪退、不耗电。不能出现“用着用着突然卡一下”的情况。也不能让用户觉得“这App是电老虎”。
我在项目中遇到过这样一个场景:一个视频播放App,播放器启动速度优化到了200ms以内,但用户还是觉得“慢”。后来发现,是启动时的黑屏过渡让用户产生了“慢”的错觉。你看,性能优化不只是数字上的提升,更是感知上的优化。
我的经验:性能优化的目标,最终要落到“用户感知”上。你优化了100ms,用户感觉不到,那这100ms的优化价值就打了折扣。优先优化那些用户“能感觉到”的卡顿点。
性能优化的核心指标
做性能优化,不能靠感觉。你得有数据。我习惯用以下五个核心指标来衡量App的性能状况:
| 指标 | 含义 | 健康阈值 | 我踩过的坑 |
|---|---|---|---|
| FPS | 帧率,每秒画面刷新次数 | ≥ 55 FPS(稳定) | 曾经以为60FPS就完美了,忽略了帧率抖动 |
| 内存 | App占用的RAM大小 | ≤ 200MB(常规App) | 内存泄漏导致OOM,线上崩溃率飙升 |
| CPU | 处理器占用率 | ≤ 30%(空闲状态) | 后台线程死循环,CPU飙到80%,手机发烫 |
| IO | 文件读写、数据库操作 | 单次读写 ≤ 10ms | 主线程做数据库查询,ANR频发 |
| 网络 | 请求响应时间、流量消耗 | 首包 ≤ 500ms | 接口返回数据量太大,弱网下直接超时 |
1. FPS(帧率)
FPS是最直观的性能指标。Android系统每16ms刷新一次画面,也就是60FPS。如果一次绘制超过16ms,就会发生掉帧。
但这里有个坑——平均FPS高不代表流畅。我曾经优化过一个App,平均FPS是58,但用户还是觉得卡。为什么?因为帧率抖动太严重了。前一秒60FPS,后一秒突然掉到20FPS,这种“忽快忽慢”的感觉比一直卡更难受。
注意:不要只看平均FPS。要关注“帧率抖动”和“掉帧次数”。我习惯用Systrace或Perfetto抓取帧渲染时间,看有没有超过16ms的帧。
2. 内存
内存优化,说白了就是管好你的对象。Java对象在堆上分配,GC会回收不再使用的对象。但GC本身也会消耗CPU,频繁GC会导致掉帧。
我记得有一次,一个图片加载功能,每次滑动列表都创建新的Bitmap对象,旧的Bitmap又不及时回收。结果内存占用从80MB一路飙到300MB,GC频繁触发,列表滑动卡成狗。
解决方案?用对象池复用Bitmap,配合LRU缓存。内存占用降到了120MB,滑动流畅了。
3. CPU
CPU占用率过高,通常意味着有“坏代码”在疯狂计算。比如:
- 在循环里做耗时操作
- 频繁创建和销毁线程
- 死循环或无限递归
我建议用Profiler抓一下CPU的火焰图,看看哪个函数占用了最多的CPU时间。我曾经发现一个排序算法在列表数据变化时被重复调用,优化后CPU占用从40%降到了5%。
4. IO
IO操作,包括文件读写、数据库查询、SharedPreferences读写。这些操作如果放在主线程,就是ANR的温床。
我曾经犯过一个错误:在列表滑动时,每次getView都去读一次数据库。结果数据库查询耗时50ms,主线程被阻塞,列表卡顿。后来改成预加载+缓存,单次查询耗时降到了1ms。
避坑指南:IO操作一定要异步。用Room或SQLite时,注意在主线程查询会抛异常(Room默认不允许主线程查询)。SharedPreferences的apply()是异步的,commit()是同步的,别搞混了。
5. 网络
网络优化,核心是“少请求、小数据、快响应”。
我见过一个App,每次启动时同时发起20个网络请求,结果弱网下全部超时,用户等了一分钟才看到内容。优化方案:合并请求、使用HTTP/2多路复用、数据压缩(Gzip/Protobuf)、本地缓存。
还有一个细节:DNS解析也会耗时。我习惯在App启动时预解析常用域名,或者直接使用IP直连。
知识体系总览
下面这张图,是我对Android性能优化知识体系的梳理。你可以把它当作一张“地图”,后续的章节都会围绕这些核心指标展开。
这张图展示了性能优化的五个核心指标,以及每个指标下的关键优化方向。后续的章节,我们会逐一深入每个指标,讲清楚“怎么测”、“怎么分析”、“怎么优化”。
总结一下:性能优化不是一锤子买卖,而是一个持续迭代的过程。先建立指标监控体系,再针对性地优化,最后验证效果。我习惯在每个版本发布前,跑一遍性能基线测试,确保没有引入新的性能问题。
好了,这一章就聊到这儿。下一章,我们会深入FPS优化,聊聊怎么让App的每一帧都丝般顺滑。