3. Application 初始化配置:自动安装、自定义监听、延迟初始化
3.1 原理概述
LeakCanary 的初始化触发点位于 ContentProvider 的 onCreate 方法中。Android 系统在 Application 的 onCreate 执行前会自动调用所有注册的 ContentProvider,从而“无侵入”地完成 LeakCanary 安装。这种自动安装方式虽然便捷,但在复杂业务场景下可能需要调整:
- 自动安装:默认行为,无需任何代码,通过 Manifest 中声明的
InternalLeakCanaryProvider自动注册。 - 自定义监听:替换或扩展默认的泄漏分析行为,例如自定义堆转储处理、上报到后端。
- 延迟初始化:将初始化时机推迟到 Application
onCreate结束甚至用户首次交互之后,降低冷启动耗时。
3.2 三种初始化方式的实现流程
| 方式 | 触发时机 | 核心代码/配置 | 适用场景 |
|---|---|---|---|
| 自动安装 | ContentProvider.onCreate(APP启动早期) | 无配置,依赖库默认注册 | 调试环境,快速接入 |
| 自定义监听 | ContentProvider.onCreate 后立即执行 | 实现 OnHeapAnalyzedListener 并通过 LeakCanary.config 注入 |
需定制堆转储处理或上报 |
| 延迟初始化 | Application.onCreate 末尾或首次进入主界面 | 在 Application 类中手动调用 LeakCanary.install(application) |
对启动耗时敏感的生产/灰度环境 |
3.3 核心代码与 API
3.3.1 自动安装(默认)
只需在 build.gradle 中添加依赖,无需任何初始化代码:
dependencies {
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
}
LeakCanary 自动通过 InternalLeakCanaryProvider 完成安装,内部创建 LeakCanary.Config 并调用 LeakCanary.install(application)。
3.3.2 自定义监听
在 Application 的 onCreate 中覆写默认配置:
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// 仅在 debug 构建中触发,避免 Release 包被误配置
if (LeakCanary.isInAnalyzerProcess) return
val customListener = OnHeapAnalyzedListener { heapAnalysis ->
// 自定义处理:保存到文件、上报服务器等
heapAnalysis.let {
Log.d("LeakCanary", "分析结果: ${it.toString().take(200)}")
}
}
LeakCanary.config = LeakCanary.config.copy(
onHeapAnalyzedListener = customListener,
// 可一并自定义其他参数,例如最大重试次数
maxStoredHeapDumps = 5
)
// 注意:不能再次调用 LeakCanary.install,否则会重复初始化
}
}
3.3.3 延迟初始化
需要禁用自动安装,再手动在合适时机调用:
// 在 Application 的 onCreate 最开始禁用自动安装
LeakCanary.config = LeakCanary.config.copy(
// 若不想使用默认监听,可设为空或自定义
onHeapAnalyzedListener = OnHeapAnalyzedListener { /* noop */ }
)
// 随后在延迟点(如首次 Activity onResume)再真正安装
// 注意:延迟安装需在非 analyzer 进程中执行
if (!LeakCanary.isInAnalyzerProcess) {
// 使用 Handler 延迟 2 秒后安装
Handler(mainLooper).postDelayed({
LeakCanary.install(application)
}, 2000)
}
3.4 调试与验证
- Log 关键字:在 Logcat 中过滤
"LeakCanary",查看是否有"LeakCanary is enabled"或"Installing LeakCanary"日志。 - 断点检查:在自定义监听器的回调中设置断点,验证泄漏分析时是否进入自定义逻辑。
- 耗时测量:在 Application 的
onCreate开始和结尾记录时间戳,对比延迟初始化和自动安装的启动耗时差异。
3.5 常见错误与避坑
⚠️ 重复初始化
手动调用
手动调用
LeakCanary.install() 时必须确保全局只执行一次。若同时使用了默认自动安装和手动安装,会导致二次初始化,可能引发 IllegalStateException。建议在延迟初始化时先设置 LeakCanary.config = … 并标记已初始化状态。
💡 关键原则
LeakCanary.config 的赋值操作必须在 LeakCanary.install() 之前完成。如果先调用了 install(),后续的 config 修改将不会生效。最佳实践是在 Application 的 onCreate 最顶部设置 config。
- ContentProvider 冲突:如果项目中也自定义了 ContentProvider,注意其优先级和进程隔离,避免 LeakCanary 的 ContentProvider 被主进程以外的 Context 调用。
- 线程安全问题:在延迟初始化时如果使用异步线程执行,需确保在 UI 线程调用
LeakCanary.install,因为 LeakCanary 内部依赖主线程的 Handler。
3.6 性能与稳定性优化
- 启动耗时优化:自动安装会在 ContentProvider 中执行耗时较短的初始化,但依然增加了 Zygote 后的启动路径。延迟初始化可将此部分移至用户可见的首帧之后,对冷启动时间敏感的应用推荐使用。
- 进程隔离:LeakCanary 会创建独立的分析进程
leakcanary。初始化时通过LeakCanary.isInAnalyzerProcess判断,避免重复初始化。 - 最小配置原则:自定义监听时避免在回调中执行长时间操作,否则会阻塞分析队列。如需上报,采用异步任务。
3.7 初始化决策流程图
3.8 部署建议
- 在 Release 包中务必移除或禁用 LeakCanary 依赖,或通过 build 变体(如
debugImplementation)仅在调试版本生效。 - 若需在 Release 包保留(例如灰度检测),确保关闭自动安装并在用户无感知时机延迟初始化,且自定义监听中不包含敏感日志。