一、内存泄漏(Memory Leak)
1、场景及原因
- 静态变量持有Context:静态对象(如单例)长期持有Activity引用,导致Activity无法回收。
- 匿名内部类:Handler、Runnable等内部类隐式持有外部类(如Activity)的引用。
- 未释放监听器或广播:注册的广播接收器(BroadcastReceiver)或事件监听未在组件销毁时注销。
- 资源未关闭:文件流、数据库连接未及时关闭。
2、优化策略及实现示例
- 弱引用替代强引用 :使用
WeakReference
或WeakHandler
避免对象被长期持有。
java
private static class SafeHandler extends Handler {
private WeakReference<Activity> activityRef;
SafeHandler(Activity activity) {
activityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
Activity activity = activityRef.get();
if (activity == null) return;
// 处理消息
}
}
- 生命周期管理 :在
onDestroy()
中注销监听器和广播,释放资源(如关闭数据库连接)。 - 静态内部类:将Handler等组件定义为静态内部类,并通过弱引用持有外部类。
- 工具检测:集成LeakCanary自动检测内存泄漏,或使用Android Profiler手动分析堆转储。
二、UI卡顿(UI Jank)
1、场景及原因
- 主线程耗时操作:在UI线程执行文件读写、网络请求或复杂计算。
- 复杂布局 :嵌套层级过深导致
onMeasure
/onLayout
耗时超过16ms。 - 过度绘制(Overdraw) :同一区域多次绘制(如多层背景叠加)。
- 频繁GC:短时间大量对象创建/销毁引发内存抖动,阻塞主线程。
2、优化策略及实现示例
- 异步处理耗时任务
- 使用Kotlin协程、RxJava或
AsyncTask
将任务移至后台线程。
- 使用Kotlin协程、RxJava或
- 布局优化
- 使用
ConstraintLayout
减少嵌套层级,替代LinearLayout
/RelativeLayout
。 - 利用
<include>
和<merge>
标签复用布局,或通过ViewStub
延迟加载不可见视图。
- 使用
- 过度绘制
- 移除冗余背景色(如父布局和子布局重复设置背景)。
- 在自定义View的
onDraw()
中使用canvas.clipRect()
限制绘制区域。
- 检测工具
- 通过Android Studio的
Layout Inspector
分析布局层级,或开启开发者选项中的GPU过度绘制
功能,目标为蓝色区域占比最大化。
- 通过Android Studio的
三、应用启动时间过长
Android 冷启动优化实践:含主线程优化、资源预加载与懒加载、跨进程预热等
1、场景及原因
- 冷启动初始化任务过多:主线程加载大量资源或初始化第三方库。
- 主题初始化延迟:默认主题的窗口背景导致白屏时间过长。
2、优化策略及实现示例
-
异步与延迟初始化 :
- 使用
Jetpack App Startup
库管理组件初始化顺序,延迟非必要任务。 - 将三方SDK、日志库等非核心初始化移至后台线程。
- 使用
-
启动主题优化 :
- 设置透明背景主题避免白屏:
xml<style name="AppTheme.Launcher"> <item name="android:windowBackground">@drawable/splash_background</item> </style>
- 在
Activity#onCreate()
中切换回正常主题。
-
工具分析 :
- 使用Android Profiler的Startup Tracing功能定位耗时操作。
四、ANR
1、场景及原因
- 主线程阻塞超过5秒:如数据库查询、密集计算。
- BroadcastReceiver超时 :
onReceive()
执行超过10秒。
2、优化策略及实现示例
-
异步处理 :使用
Room
的异步查询或WorkManager
执行后台任务。kotlin@Query("SELECT * FROM users") suspend fun getUsers(): List<User> // 协程支持
-
避免主线程I/O操作 :通过
StrictMode
检测违规代码:kotlinStrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads().detectDiskWrites().penaltyLog().build());
五、电池消耗过快
1、场景及原因
- 频繁唤醒(WakeLock) :未及时释放导致CPU持续运行。
- 传感器滥用:GPS或加速度传感器持续监听。
- 网络请求频繁:移动网络下射频模块频繁切换。
2、优化策略及实现示例
-
任务合并与延迟 :
- 使用
JobScheduler
或WorkManager
在充电或WiFi下批量执行任务。
- 使用
-
传感器管理 :
- 在
onPause()
中注销传感器监听:
kotlinsensorManager.unregisterListener(this);
- 在
-
网络优化 :
- 使用
Battery Historian
分析耗电原因,减少移动网络下的请求频率。
- 使用
六、APK包体积过大
1、可能原因
- 大量的图片资源 :
- 应用中使用了大量的高清图片、图标等资源,会使安装包体积增大。例如,一个游戏应用中包含了大量的角色图片、场景图片。
- 未优化的第三方库 :
- 引入的第三方库可能包含了一些不必要的代码和资源,导致安装包体积膨胀。
- 多渠道资源冗余 :
- 在进行多渠道打包时,如果没有对资源进行合理的配置和优化,会导致不同渠道的安装包中存在大量重复的资源。
2、优化策略及步骤
- 图片资源优化 :
- 对图片进行压缩处理,选择合适的图片格式。可以使用 tinypng 等工具对图片进行压缩。
- 第三方库优化 :
- 仔细分析第三方库的使用情况,去除不必要的依赖。可以使用 ProGuard 等工具对代码进行混淆和优化,去除无用的代码和资源。
- 多渠道打包优化 :
- 使用 Gradle 的多渠道打包功能,对不同渠道的资源进行差异化配置,避免资源冗余。
七、总结与建议
- 检测工具 :
- Android Profiler(内存/CPU/网络)。
- Systrace(系统级性能分析)。
- LeakCanary(内存泄漏)。
- 持续优化流程 :
- 性能优化需贯穿开发周期,结合自动化测试(如Jetpack Benchmark)和线上监控(Firebase Crashlytics)。
通过上述策略,开发者可系统性解决Android应用的性能问题,提升用户体验。具体实现时需结合项目实际场景,避免过度优化引入复杂性。