🧠 Android 内存优化:系统化、可落地的实践指南
📌 1. 内存优化的核心目标
- 减少不必要的内存占用
- 降低 GC 频率与停顿时间
- 避免内存泄漏
- 提升应用稳定性与流畅度
你作为技术架构师最关心的其实是:如何让团队写出的代码天然更省内存、更可控、更可维护。下面的内容完全围绕这个目标展开。
🧩 2. Android 内存结构(快速复盘)
| 区域 | 内容 | 优化关注点 |
|---|---|---|
| Java Heap | 对象、Bitmap、集合等 | 泄漏、对象复用、Bitmap 管理 |
| Native Heap | C/C++、Bitmap、RenderScript | 大图、NDK 泄漏 |
| Stack | 线程栈 | 线程数量 |
| Code | Dex、So | 多 Dex、动态加载 |
| Graphics | GPU 纹理 | 大图、过度绘制 |
🕳️ 3. 常见内存问题与根因模型(Root Cause Model)
🔥 3.1 内存泄漏(Leaking)
典型来源:
- 持有 Context(尤其是 Activity)引用
- 静态变量持有 View / Context
- 匿名内部类、Handler、Runnable
- 单例持有 Activity
- 未注销的 Listener、Receiver、Callback
- WebView 未正确销毁
团队可复用检查清单:
代码
□ 是否持有 Activity/Fragment 引用?
□ 是否注册了 listener / callback?是否在 onDestroy 中注销?
□ 是否使用了匿名内部类?是否改为 static + WeakReference?
□ 是否使用了单例?是否持有 Context?
□ 是否使用了 WebView?是否调用 destroy()?
🧹 4. GC 行为与优化策略
🚀 4.1 减少对象创建
- 使用 对象池(如 RecyclerView ViewHolder、BitmapPool)
- 避免频繁创建临时对象(尤其在 onDraw)
- 使用 StringBuilder 替代字符串拼接
🚀 4.2 降低 GC 压力
- 避免大对象(>1MB)频繁创建
- 避免在 UI 线程触发 GC(卡顿来源)
- 使用合适的数据结构(SparseArray 替代 HashMap)
🖼️ 5. Bitmap 与图片优化(高收益区)
🎯 5.1 加载优化
- 使用
inSampleSize压缩 - 使用
RGB_565替代ARGB_8888(非透明图) - 使用 LruCache 缓存 Bitmap
🎯 5.2 避免 OOM
- 不在主线程 decode
- decode 前先 decode bounds
- 使用 Glide/Fresco 等成熟库(自动复用 Bitmap)
🧱 6. 自定义 View 内存优化(你最擅长的领域)
🎨 6.1 onDraw 避免创建对象
错误示例:
kotlin
override fun onDraw(canvas: Canvas) {
val paint = Paint() // ❌ 每帧创建
}
正确示例:
kotlin
private val paint = Paint()
override fun onDraw(canvas: Canvas) {
canvas.drawRect(rect, paint)
}
🎨 6.2 避免重复计算
- 复杂 Path 预计算
- Shader 复用
- Bitmap 复用
🎨 6.3 避免内存抖动(Memory Churn)
- 避免频繁创建临时对象(Rect、Path、PointF)
- 使用
Path.reset()而不是 new Path()
🧭 7. Context 使用规范(团队必备)
❌ 不要持有 Activity Context
- 单例
- 静态变量
- 工具类
- Adapter
✔️ 使用 Application Context
- Toast
- 工具类
- 单例
- 全局初始化
🧵 8. 线程与协程内存优化
⚠️ 8.1 线程泄漏
- Thread 未结束
- TimerTask 未取消
- ExecutorService 未 shutdown
✔️ 8.2 协程最佳实践
- 使用
viewModelScope - 使用
lifecycleScope - 避免 GlobalScope
- 及时取消 Job
🧩 9. 内存监控与工具链
🔍 9.1 LeakCanary(必备)
- 自动检测泄漏
- 提供泄漏路径
- 团队可统一接入
🔍 9.2 Android Studio Profiler
- Heap Dump
- Allocation Tracking
- GC 事件分析
🔍 9.3 ADB 工具
代码
adb shell dumpsys meminfo <package>
adb shell am dumpheap <pid> /sdcard/heap.hprof
🧱 10. 团队可落地的内存优化规范(可直接复制到团队文档)
📘 10.1 代码规范
- 禁止静态持有 Context
- 禁止在 onDraw 创建对象
- 必须注销 Listener/Receiver
- 必须使用 Application Context(除非 UI 相关)
- 必须使用 LruCache 管理 Bitmap
📘 10.2 架构规范
- ViewModel 持有数据,不持有 View
- Repository 不持有 Context
- 单例不持有 Activity
📘 10.3 自定义 View 规范
- Paint/Path/Rect 复用
- Bitmap 复用
- onMeasure/onLayout/onDraw 不创建对象