android 性能优化 详解

Android 性能优化是一个系统性工程,涵盖多个维度。以下是核心优化方向的详细解析:


一、内存优化

1.1 内存泄漏排查

泄漏类型 常见场景 解决方案
静态引用 static 持有 Activity/Context 使用 WeakReference,避免静态持有
匿名内部类 HandlerAsyncTask 持有外部类引用 使用静态内部类 + WeakReference
资源未释放 BitmapCursorStream 未关闭 try-finallytry-with-resources
监听器未注销 BroadcastReceiverLocationListener 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 大对象与内存监控

  • 使用 ProfilerLeakCanary 检测泄漏

  • 关注 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 启动优化策略

  1. 异步初始化 :使用 Coroutine / HandlerThread 将非必要初始化移出主线程

  2. 延迟加载 :使用 IdleHandler 在主线程空闲时执行

  3. ContentProvider 优化 :避免在 Application.onCreate() 前执行耗时操作

  4. 布局预加载 :使用 ViewStubAsyncLayoutInflater

  5. 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 线程管理

  • 使用线程池替代裸线程(ExecutorsThreadPoolExecutor

  • 避免线程泄漏和线程数爆炸

  • Kotlin 优先使用 Coroutine(轻量级线程)


十、性能优化检查清单

复制代码
□ 使用 LeakCanary 检查内存泄漏
□ 使用 Profiler 分析 CPU 和内存热点
□ 检查过度绘制(GPU 过度绘制调试)
□ 确保列表使用 RecyclerView + ViewHolder
□ 启动时间 < 1.5s(冷启动)
□ 图片使用 WebP + 采样压缩
□ 后台任务使用 WorkManager
□ 使用 DataStore/MMKV 替代 SP
□ 启用 R8 代码压缩和资源缩减
□ 使用 ConstraintLayout 减少布局层级
相关推荐
vortex51 小时前
composer.json 可写场景下的利用手段
android·json·composer
studyForMokey1 小时前
【Android 内存管理】JVM 内存模型与 GC 原理
android·jvm
夜雪一千13 小时前
MySQL 全局锁是什么?原理、风险、备份踩坑完整实战
android·mysql·adb
又见情义19 小时前
RK3568 Android 13 驱动适配实战:从零开始让SDK在自己的板子上跑起来
android·arm开发·驱动开发
霸道流氓气质20 小时前
MySQL 大表 DDL 变更 — 原理、方案与实践
android·数据库·mysql
明雨-开发21 小时前
Android打包时候Execution failed for task ‘:launcher:lintVitalAnalyzeRelease‘.
android
游戏开发爱好者821 小时前
开心上架是什么,一站式 Apple 开发者工作台总览
android·小程序·https·uni-app·iphone·webview
Android-Flutter21 小时前
android kotlin launch 源码分析
android·kotlin
Android-Flutter1 天前
android kotlin 状态机 Continuation 详解
android·kotlin