Android 性能优化是一个系统性工程,涵盖多个维度。以下是核心优化方向的详细解析:
一、内存优化
1.1 内存泄漏排查
| 静态引用 | static 持有 Activity/Context | 使用 WeakReference,避免静态持有 |
| 匿名内部类 | Handler、AsyncTask 持有外部类引用 | 使用静态内部类 + WeakReference |
| 资源未释放 | Bitmap、Cursor、Stream 未关闭 | try-finally 或 try-with-resources |
| 监听器未注销 | BroadcastReceiver、LocationListener | 在 onDestroy() 中注销 |
| 单例模式滥用 | 单例持有 Activity 引用 | 传入 ApplicationContext |
1.2 内存抖动(Memory Churn)
-
现象:频繁创建和销毁对象,导致 GC 频繁触发,UI 卡顿
-
优化手段:
-
对象池复用(如 Message.obtain()、RecyclerView 的 ViewHolder)
-
避免在 onDraw()/onMeasure() 中创建对象
-
使用 StringBuilder 替代字符串拼接
-
使用 SparseArray 替代 HashMap<Integer, Object>
-
1.3 Bitmap 优化
java
// 1. 采样率压缩
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2; // 宽高各压缩为 1/2
Bitmap bitmap = BitmapFactory.decodeResource(res, resId, options);
// 2. 复用内存(Android 3.0+)
options.inBitmap = reusedBitmap;
// 3. 使用合适的图片格式
// ARGB_8888 (4字节/像素) → RGB_565 (2字节/像素,无透明)
1.4 大对象与内存监控
-
使用 Profiler 或 LeakCanary 检测泄漏
-
关注 LargeHeap 属性(谨慎使用)
-
使用 onTrimMemory(int level) 释放缓存
二、UI 渲染优化
2.1 渲染管线与 16ms 原则
Android 每帧需在 16ms 内完成(60fps),否则出现掉帧。
plain
CPU (Measure → Layout → Draw) → GPU (Rasterization → Display)
2.2 过度绘制(Overdraw)
-
检测:开发者选项 → 调试 GPU 过度绘制
-
优化:
-
移除不必要的背景(windowBackground 与根布局背景重复)
-
使用 <merge> 标签减少层级
-
使用 clipRect() 和 quickReject() 裁剪不可见区域
-
自定义 View 时避免在 onDraw() 中绘制被遮挡的部分
-
2.3 布局层级优化
| ConstraintLayout | 扁平化布局,替代多层嵌套 |
| ViewStub | 按需加载(延迟初始化) |
| <include> + <merge> | 复用布局,减少层级 |
| 避免使用 RelativeLayout | 性能较差,已废弃 |
2.4 列表优化(RecyclerView)
-
使用 DiffUtil 局部更新,避免 notifyDataSetChanged()
-
设置 setHasFixedSize(true) 优化布局计算
-
图片加载使用占位图 + 三级缓存
-
分页加载(Paging 3)
三、启动优化
3.1 冷启动 vs 热启动
plain
冷启动:App 进程不存在 → 创建进程 → Application → Activity 创建
热启动:进程存在,Activity 被回收后重建
3.2 启动优化策略
异步初始化:使用 Coroutine / HandlerThread 将非必要初始化移出主线程
延迟加载:使用 IdleHandler 在主线程空闲时执行
ContentProvider 优化:避免在 Application.onCreate() 前执行耗时操作
布局预加载:使用 ViewStub 或 AsyncLayoutInflater
Multidex 优化:Android 5.0 以下使用 MultiDex,考虑代码拆分
3.3 启动时间测量
bash
adb shell am start -W com.package.name/.MainActivity
# 关注 TotalTime(从 AMS 到 Activity 显示)
四、电量优化
4.1 Doze 模式与 App Standby
-
Doze 模式:设备静止且未充电时,延迟后台任务
-
App Standby:长期未使用的 App 限制后台活动
4.2 后台任务优化
表格
| 定时任务 | WorkManager(兼容 Doze) |
| 网络请求 | JobScheduler / WorkManager |
| 定位 | 降低更新频率,使用 FusedLocationProvider |
| 唤醒锁 | 避免滥用 WakeLock,使用 WakefulBroadcastReceiver |
4.3 传感器与硬件
-
及时注销传感器监听(SensorManager.unregisterListener)
-
使用 JobScheduler 批量网络请求
-
避免频繁使用 AlarmManager(使用 setAndAllowWhileIdle)
五、APK 体积优化
5.1 代码层面
-
ProGuard/R8:代码混淆、移除无用代码
-
资源缩减:shrinkResources true
-
移除多语言支持:resConfigs "zh", "en"
-
使用 Android App Bundle (AAB):动态交付
5.2 资源层面
| 图片 | WebP 格式(比 PNG 小 25-35%)、Vector Drawable |
| 音频 | 使用 OGG 替代 WAV |
| 字体 | 仅包含需要的字重,使用可下载字体 |
| 原生库 | abiFilters 过滤不需要的 ABI(如 arm64-v8a) |
六、网络优化
6.1 请求优化
-
连接复用:HTTP/2 多路复用、Keep-Alive
-
请求合并:批量接口替代多次单条请求
-
数据压缩:Gzip、Protocol Buffers
-
缓存策略:OkHttp 缓存、Room 本地持久化
6.2 弱网优化
-
超时重试机制(指数退避)
-
图片降级(弱网加载低分辨率图)
-
失败队列 + 网络恢复后重试
七、存储与 I/O 优化
7.1 SharedPreferences 优化
-
问题:commit() 同步写磁盘、全量替换 XML
-
替代方案:
-
DataStore(Kotlin 协程,类型安全)
-
MMKV(腾讯开源,mmap 内存映射,性能高 100 倍)
-
7.2 数据库优化
-
使用索引加速查询
-
批量操作使用事务(beginTransaction())
-
使用 Room 的 @Fts4 全文搜索
-
避免主线程查询(allowMainThreadQueries() 仅调试)
7.3 文件操作
-
使用 BufferedInputStream/BufferedOutputStream
-
大文件使用 MappedByteBuffer(内存映射)
-
避免在 SharedPreferences 中存储大对象
八、卡顿与 ANR 分析
8.1 ANR 触发条件
-
主线程 5 秒内未响应输入事件
-
BroadcastReceiver 10 秒内未完成
-
Service 20 秒内未执行完 onStartCommand()
8.2 分析工具
| Systrace | 分析 CPU、渲染、IO 等系统级耗时 |
| Profiler (Android Studio) | CPU、Memory、Network、Energy 实时监控 |
| Choreographer | 帧率监控:Choreographer.getInstance().postFrameCallback() |
| StrictMode | 检测主线程 IO、内存泄漏 |
九、架构层面的优化
9.1 模块化与组件化
-
按业务拆分模块,减少编译时间
-
使用 AAR 依赖替代源码依赖
-
路由解耦(ARouter 等)
9.2 线程管理
-
使用线程池替代裸线程(Executors、ThreadPoolExecutor)
-
避免线程泄漏和线程数爆炸
-
Kotlin 优先使用 Coroutine(轻量级线程)
十、性能优化检查清单
□ 使用 LeakCanary 检查内存泄漏
□ 使用 Profiler 分析 CPU 和内存热点
□ 检查过度绘制(GPU 过度绘制调试)
□ 确保列表使用 RecyclerView + ViewHolder
□ 启动时间 < 1.5s(冷启动)
□ 图片使用 WebP + 采样压缩
□ 后台任务使用 WorkManager
□ 使用 DataStore/MMKV 替代 SP
□ 启用 R8 代码压缩和资源缩减
□ 使用 ConstraintLayout 减少布局层级





