Android 开发手册ANDROID DEV

CHAPTER 09体验底线 · PERFORMANCE

内存与性能优化

卡顿、崩溃、发热会让用户卸载。本章讲透 ART 内存、内存泄漏、启动优化、渲染与卡顿、电量与后台限制。

开始阅读难度高阶约2.5小时
09.1

ART 与内存

Android 运行在 ART(Android Runtime),分代 GC 回收对象。频繁分配大对象/短命对象会触发 GC 卡顿,应复用与对象池。

关注分配率

高分配率(allocations/sec)引起频繁 GC,表现为周期性掉帧。用 Profiler 的 Memory 面板查看分配热点。

09.2

内存泄漏

长生命周期对象(单例、静态)持有 Activity/Fragment/Context 强引用,导致本应回收的界面无法释放。

// 反例:单例持 Activity 引用 → 泄漏
object Analytics { lateinit var ctx: Context }   // 用 ApplicationContext
// 正例
object Analytics { lateinit var ctx: ApplicationContext }
09.3

LeakCanary

LeakCanary 在开发包自动检测 Activity/Fragment 泄漏,堆转储并展示引用链,是定位泄漏的利器。

仅 debug 依赖

用 debugImplementation 引入,release 自动移除,不影响生产体积。

09.4

启动优化

冷启动分系统进程创建→Application→首屏绘制。减少 Application.onCreate 与主线程同步重活是核心。

// 反例:Application 里同步初始化重活
override fun onCreate() { super.onCreate(); initHugeSDK()  /* 阻塞 */ }
// 正例:延迟到首屏之后
lifecycleScope.launch(Dispatchers.Default) { initHugeSDK() }
基线 Profile

用 Baseline Profile 预编译关键路径,可显著缩短冷启动,是官方推荐手段。

09.5

渲染与卡顿

每帧 16ms(60fps)预算,超期即掉帧(jank)。过度绘制(多层重叠背景)、主线程重活、频繁布局是主因。

主线程纪律

网络、数据库、图片解码必须离主线程;用协程 Dispatchers.IO/Default 与 Coil/Glide 后台加载。

09.6

列表性能

RecyclerView 用 DiffUtil/ListAdapter 只更新变化项;避免在 onBind 里做分配或 IO;图片用异步库并复用。

09.7

电量与后台

Doze 模式与后台限制会挂起后台任务。合并网络、用 WorkManager 调度可延迟工作、定位用单次获取而非常驻。

  • WorkManager。持久化、可约束(充电/联网)的后台任务。
  • 合并请求。减少射频唤醒次数。
  • 定位按需。单次 getCurrentLocation 而非持续监听。
09.8

常见陷阱

为什么内存只涨不跌?

基本是泄漏:长生命周期对象持有界面。用 LeakCanary 抓引用链,把 Context 换成 ApplicationContext、解绑监听。

列表滑动掉帧怎么查?

用 CPU Profiler 抓主线程热点,通常 onBind 里有同步解码/分配。移到后台、用 DiffUtil 减少刷新。

09.9

实战练习

延伸资源