Android随笔-性能优化
一、启动优化1.1 启动类型定义App启动分三种优化策略完全不同类型定义优化重点冷启动进程不存在系统重新创建进程减少Application初始化、首屏布局复杂度热启动进程在后台Activity从后台恢复避免onResume中做耗时操作温启动进程存在但Activity被回收需重建介于两者之间减少Activity重建开销冷启动的完整流程系统创建进程 → 加载Application → 启动ActivityThread → 创建MainActivity → 渲染视图 → 替换空白Window → 首屏可交互。1.2 启动耗时测量本地测量# 测量冷启动时间adb shell am start-W包名/.MainActivity# 输出ThisTime最后一个Activity启动耗时、TotalTime所有Activity启动总耗时、WaitTimeAMS启动Activity总耗时线上监控用 Macrobenchmark StartupTimingMetric 做可重复的冷/温/热启动测量发布侧用 Baseline Profiles 改善首次启动编译线上看 Android Vitals 的 App startup time、ANR、slow/frozen frames1.3 核心优化手段1Application初始化减负延迟初始化非必要SDK统计、推送、广告等用 ContentProvider 的 onCreate 做懒加载或 Handler.postDelayed(500ms) 避开启动高峰第三方SDK接口替换某地图SDK初始化时同步读取 /data 目录改为 Context.getExternalFilesDir() 获取私有目录避免磁盘IO阻塞用 Dagger 等依赖注入框架首次注入时才创建对象2Dex分包优化通过 multiDexKeepProguard 规则将核心启动类保留在主Dex非核心类拆分至二级Dex实测主Dex文件缩小42%类加载耗时减少180ms3首屏布局优化合并 SplashActivity 与 MainActivity避免连续启动两个Activity带来的百毫秒级劣化广告从Activity形式改为View形式在MainActivity#onCreate中添加到DecorView广告展示时底下首页框架可预加载用 ViewStub 延迟加载非首屏内容减少初始布局解析时间4GC抑制启动阶段任务众多极易触发GC带来性能损耗通过Profiler排查启动过程中的对象创建找出分配过于频繁的场景高级方案影响ART虚拟机默认GC行为进行GC抑制需评估稳定性和兼容性5系统级调优CPU频率调优启动阶段临时提升CPU大核频率I/O优先级提升将应用数据目录的I/O优先级设置为实时调度进程预加载针对高频用户在系统层实现应用进程预加载提前触发Zygote进程分叉二、内存优化2.1 内存泄漏检测与修复检测工具链工具用途适用场景Android Studio Profiler实时内存监控、堆转储分析开发期定位问题LeakCanary自动化检测Activity/Fragment泄漏开发期自动告警MAT深度分析hprof文件查看引用链线下深度排查StrictMode检测Activity泄漏、未关闭资源、SQLite未关闭开发期预防常见泄漏场景及修复单例持有Activity Context改用 getApplicationContext()Handler/Runnable匿名内部类改为静态内部类 WeakReferenceonDestroy中移除所有消息广播/传感器/定位监听器未注销在 onDestroy/onPause 中成对取消注册资源对象未关闭Cursor、File、Bitmap等用 try-with-resources 确保关闭WebView在 onDestroy 中调用 webView.destroy() 和 webView null线上内存监控方案方案1内存占用超过80%时抓取堆快照裁剪后上传服务器分析方案2改造LeakCanary带到线上只分析大对象内存泄漏元凶降低分析内存占用方案3监控App整体GC次数、重点模块GC次数、GC耗费时间2.2 内存优化策略数据结构优化避免 HashMapInteger, Object 的自动装箱用 SparseArray/ArrayMap 替代用 ArrayList 替代 LinkedList减少内存占用避免使用枚举用常量替代Bitmap大图优化用 BitmapFactory.Options 的 inSampleSize 采样加载用 Glide/Coil 自动管理内存和磁盘缓存设置 inBitmap 复用Bitmap内存避免频繁分配对象池与复用高频创建的对象如 Paint、Rect用对象池或静态成员自定义View的 onDraw 中禁止创建对象其他细节谨慎使用 SharedPreference初始化时将全部数据加载到内存数据量大时持续占用内存谨慎使用外部库避免同质化框架重复引入注册 onTrimMemory() 回调根据内存等级释放资源三、渲染优化UI流畅度3.1 过度绘制优化检测开发者选项 → 调试GPU过度绘制蓝色1次绘制绿色2次红色4次优化手段移除Window默认背景window.setBackgroundDrawable(null)如果内容布局有背景移除Activity背景RecyclerView有背景时移除item背景所有子View都有背景时移除父View背景使用9-patch图减少过度绘制拉伸区域透明3.2 布局层级优化用 ConstraintLayout 替代多层嵌套将布局层级从9层降至3层用 merge 标签减少View数量include 复用布局用 ViewStub 延迟加载不常用布局clipChildren false 允许子View绘制在父View边界外减少不必要的裁剪重绘3.3 RecyclerView深度优化优化点具体做法固定高度setHasFixedSize(true)避免requestLayout浪费资源缓存调优setItemViewCacheSize(4)加大离屏缓存用空间换时间禁用动画((SimpleItemAnimator)rv.getItemAnimator()).setSupportsChangeAnimations(false)共用缓存池嵌套RecyclerView时setRecycledViewPool(pool)共用Pool预解析布局子线程用AsyncLayoutInflater预解析复杂卡片布局监听复用不要对每个Item都调用addXxListener公用Listener根据ID区分操作图片加载控制滑动时暂停加载停止滑动后再加载稳定IDsetHasStableIds(true)避免增删时无关视图刷新3.4 自定义View优化onDraw 中避免创建对象Paint、Rect等提前初始化用 clipRect 减少绘制区域复杂静态View用 setLayerType(LAYER_TYPE_HARDWARE) 硬件缓存用 StaticLayout 或 DynamicLayout 自定义View替代TextView避免每次测量四、电量优化4.1 耗电四大元凶WakeLock唤醒锁滥用未及时释放、长时间持有PartialWakeLockCPU持续唤醒无法休眠后台频繁任务轮询自定义定时器、Handler循环轮询无休眠策略网络频繁请求高频心跳、频繁刷新接口、无缓存机制前台页面耗电动画冗余、刷新频率过高、传感器持续监听、屏幕常亮未关闭4.2 WorkManager统一调度为什么用WorkManager替代自定义轮询系统智能合并任务、适配休眠机制不受生命周期影响应用退出也可执行任务持久化重启手机后可恢复支持网络、充电、待机状态等触发条件classPollingWork(context:Context,params:WorkerParameters):Worker(context,params){overridefundoWork():Result{returntry{// 执行轮询任务Result.success()}catch(e:Exception){Result.retry()// 失败自动重试}}}// 配置约束条件valconstraintsConstraints.Builder().setRequiredNetworkType(NetworkType.UNMETERED)// WiFi.setRequiresCharging(true)// 充电时.setRequiresBatteryNotLow(true)// 电量不低.build()valworkRequestPeriodicWorkRequestBuilderPollingWork(15,TimeUnit.MINUTES).setConstraints(constraints).setBackoffCriteria(BackoffPolicy.EXPONENTIAL,30,TimeUnit.SECONDS).build()WorkManager.getInstance(context).enqueueUniquePeriodicWork(sync_work,ExistingPeriodicWorkPolicy.KEEP,workRequest)4.3 Doze模式适配Doze模式手机息屏、静置、未充电时自动进入限制网络、延迟任务、忽略唤醒锁。适配策略高优先级用FCM推送普通任务延迟到维护窗口执行检测Doze状态powerManager.isDeviceIdleMode在Doze模式下延迟任务到1小时后执行4.4 其他电量优化定位优化用 FusedLocationProvider降低精度/延长间隔前台时才高频定位传感器不用时及时 unregisterListener前台服务Android O 用 startForegroundService必须创建通知渠道网络降噪接口请求合并、增加本地缓存、降低心跳频率、弱网减少重试五、包体积优化5.1 资源优化优化方向关键技术预估收益无用资源清理Lint shrinkResources true减少5%~15%图片压缩WebP/AVIF AndResGuard减少10%~30%.so文件优化ABI过滤 Android App Bundle减少20%~50%第三方SDK瘦身依赖分析 模块化引入减少5%~20%具体手段resConfigs “zh”, “xxhdpi” 只保留中文和指定分辨率资源用Lint检测无用资源Analyze → Run Inspection by Name → Unused resources图片转WebP格式API 14矢量图替代多分辨率图Assets图片同格式压缩通过Gradle插件在打包时自动处理5.2 代码优化minifyEnabled true shrinkResources true 启用R8代码压缩移除未使用的类、方法、字段Dex分包策略核心类保留主Dex谨慎引入外部库避免同质化框架5.3 动态下发非核心功能主题皮肤、语言包通过热更新或按需下载so文件动态下发按ABI过滤只打包必要架构大资源通过动态资源管理平台下发CI前置管控新增资源大小六、性能监控与治理体系模块核心内容启动优化Application 减负、Dex 分包、首屏布局、GC 抑制、系统级调优内存优化泄漏检测工具链、常见泄漏场景、数据结构优化、Bitmap 大图、线上监控渲染优化过度绘制、布局层级、RecyclerView 深度优化、自定义 View电量优化耗电四大元凶、WorkManager 统一调度、Doze 模式适配包体积优化资源清理、so 优化、代码压缩、动态下发监控治理本地分析工具、线上监控方案、Baseline Profiles、优化优先级工具用途Android Studio ProfilerCPU、Memory、Network、Energy 实时分析Perfetto / Systrace系统级性能追踪分析线程调度、渲染管线Firebase Performance线上性能监控自动追踪启动时间、网络请求Battery Historian生成详细耗电报告adb bugreport bugreport.zipMacrobenchmark可重复的启动/滚动性能基准测试Baseline Profiles预编译热路径代码提升启动和运行时性能优化优先级建议第一梯队影响最大启动速度 → 渲染流畅度 → 内存泄漏第二梯队持续收益网络优化 → 包体积 → 电量消耗第三梯队精细打磨代码执行效率 → 缓存策略 → 线程调度性能优化不是一次性任务而是需要建立指标 → 监控埋点 → 定位瓶颈 → 验证收益的闭环。先用Profiler找到实际瓶颈再针对性优化避免盲目改造。