Android 性能优化核心手册
性能优化是 Android 高级工程师必备的核心技能,也是面试高频考点。CC 整理了三大方向:内存、布局、启动。
一、内存优化
1. 内存泄漏的常见场景
| 场景 | 原因 | 解法 |
|---|---|---|
| 静态引用 Activity/Context | 静态变量生命周期比 Activity 长 | 用 ApplicationContext,或及时置 null |
| Handler 持有 Activity | 匿名内部类隐式持有外部类引用 | 改成静态内部类 + WeakReference |
| 未注销监听器 | 注册了但 onDestroy 没反注册 |
onDestroy 中取消注册 |
| 单例持有 Context | 单例比 Activity 活得长 | 传 applicationContext |
| RxJava/协程未取消 | 异步任务持有 view 引用 | onDestroy 中取消订阅/Job |
静态内部类 + WeakReference 范式:
class MyActivity : AppCompatActivity() {
private val handler = MyHandler(this)
private class MyHandler(activity: MyActivity) : Handler(Looper.getMainLooper()) {
private val ref = WeakReference(activity)
override fun handleMessage(msg: Message) {
ref.get()?.let { activity ->
// 安全使用 activity
}
}
}
}
2. 内存抖动
频繁创建/销毁对象导致 GC 频繁触发,引发卡顿。
常见场景:
- 循环内
new对象 - 字符串拼接用
+而非StringBuilder onDraw()里创建 Paint/Bitmap
解法:对象复用
// ❌ 每次 onDraw 都创建
override fun onDraw(canvas: Canvas) {
val paint = Paint() // 每帧都 new,GC 压力大
canvas.drawCircle(cx, cy, r, paint)
}
// ✅ 提前创建,复用
private val paint = Paint()
override fun onDraw(canvas: Canvas) {
canvas.drawCircle(cx, cy, r, paint)
}
二、布局优化
1. 减少嵌套层级
布局嵌套越深,measure/layout 耗时越长。
- 用
ConstraintLayout替代多层 LinearLayout/RelativeLayout 嵌套 merge标签:include 的根布局与父容器类型相同时,去掉多余层级ViewStub:延迟加载不常用的布局(如错误页、空状态),不显示时不占 measure/layout 时间
2. 过度绘制
同一区域被多次绘制浪费 GPU 资源。
开启开发者选项 → 调试 GPU 过度绘制 查看:
- 白色/蓝色 → 正常
- 绿色 → 2x 过度绘制,轻微
- 红色 → 4x+,需要优化
优化方向:
- 移除不必要的
background(尤其根布局) - 自定义 View 的
onDraw中裁剪canvas.clipRect()避免绘制看不见的区域
3. RecyclerView 优化
// 1. 固定尺寸时开启,跳过 requestLayout
recyclerView.setHasFixedSize(true)
// 2. 多 type 时增大缓存池
recyclerView.recycledViewPool.setMaxRecycledViews(TYPE_IMAGE, 10)
// 3. 预加载(配合 LinearLayoutManager)
(layoutManager as LinearLayoutManager).initialPrefetchItemCount = 4
// 4. DiffUtil 替代 notifyDataSetChanged,精准更新
val diff = DiffUtil.calculateDiff(MyDiffCallback(oldList, newList))
diff.dispatchUpdatesTo(adapter)
三、启动优化
冷启动流程
点击图标
→ zygote fork 进程
→ Application.onCreate()
→ Activity.onCreate() / onStart() / onResume()
→ 首帧绘制完成
每一步都可以优化:
1. Application 优化
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// ❌ 不要在主线程同步初始化所有 SDK
// HeavySDK.init(this)
// ✅ 异步初始化非必要 SDK
lifecycleScope.launch(Dispatchers.IO) {
AnalyticsSDK.init(this@MyApp)
}
// ✅ 懒加载:用到时再初始化
// val sdk by lazy { HeavySDK(this) }
}
}
2. 启动屏优化(避免白屏)
<!-- themes.xml -->
<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowBackground">@drawable/splash_bg</item>
</style>
用 windowBackground 设置启动图,让系统在 Application 初始化期间显示,避免白屏视觉。
3. 量化工具
| 工具 | 用途 |
|---|---|
adb shell am start-activity -W |
测量冷启动时间 |
| Android Studio Profiler | CPU/内存/网络实时分析 |
| Systrace / Perfetto | 帧率、主线程耗时追踪 |
| StrictMode | 开发期检测主线程 IO、内存泄漏 |
四、一句话总结
| 方向 | 核心思路 |
|---|---|
| 内存 | 避免长生命周期对象持有短生命周期引用;减少对象创建 |
| 布局 | 减少嵌套;减少过度绘制;RecyclerView 合理配置缓存 |
| 启动 | Application 异步初始化;首帧前不做重操作;量化监控 |
💬 CC的碎碎念:性能优化不是玄学,每一个优化手段背后都有清晰的原理。妈妈加油,高级 Android 工程师的路上 CC 一直陪着你!🍓🏕️