在Android开发中,使用 LeakCanary 可以方便地检测内存泄漏(Memory Leak),帮助开发者定位和修复常见的资源泄漏问题(如 Context、Activity、Fragment 等)。以下是 LeakCanary 的使用方法 和最佳实践
-
集成 LeakCanary
从版本 2.0 起,LeakCanary 使用了更简洁的自动集成方式,无需手动初始化。- 添加依赖(build.gradle)
dependencies { // 只在 debug 包中使用 LeakCanary,避免发布到生产环境 debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12.1' // 使用 Java 的话,不需要 Core,可以只用 LeakCanary 提供的 `AppWatcher` 模块 }
-
使用 LeakCanary 监控内存泄漏
-
自动监控常见泄漏对象
LeakCanary 默认会监控以下对象的泄漏情况:- Activity
- Fragment
- ViewModel
- Service
- BroadcastReceiver
如果这些对象在销毁后没有被 GC 回收,LeakCanary 会自动检测并报告内存泄漏。
-
手动监控自定义对象(可选)
你可以使用 LeakSentry 来手动检测特定对象的释放情况:class MyManager { companion object { private var instance: MyManager? = null fun initialize(context: Context) { val ref = MyManager() LeakSentry.isDebugging = true // 可选调试 LeakSentry.watch(ref) // 监控该对象 instance = ref } } }
-
-
模拟内存泄漏测试
为了验证 LeakCanary 是否正常工作,可以模拟一个内存泄漏:class LeakActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 模拟内存泄漏 object : Thread() { override fun run() { while (true) { try { sleep(1000) } catch (e: InterruptedException) { break } } } }.start() // 持有 Activity 的静态引用,导致泄漏 LeakHolder.activity = this } override fun onDestroy() { super.onDestroy() LeakHolder.activity = null } } object LeakHolder { var activity: LeakActivity? = null }
运行 App,退出该 Activity,稍等片刻,LeakCanary 会在通知栏提示内存泄漏。
-
查看 LeakCanary 检测报告
当 LeakCanary 检测到内存泄漏后,会弹出通知,点击通知可查看详细的泄漏路径分析报告,例如┬─── │ GC Root: System class │ ├─ android.app.ActivityThread instance │ ↓ ActivityThread.mActivities │ ↓ │ android.app.ActivityThread$ActivityClientRecord.activity │ ↓ │ LeakActivity instance (leaked) │ ↓ │ LeakHolder.activity │ ↓ │ object $LeakActivity.onCreate$1 (still alive)
该报告会指出泄漏对象和引用链路,帮助快速定位问题。
-
配置 LeakCanary(可选)
- 自定义配置
class MyApplication : Application(), LeakCanaryProvider { override val appWatcher = AppWatcher.manualInstance override fun onCreate() { super.onCreate() AppWatcher.manualInstance = appWatcher( config = LeakCanary.config .copy( dumpHeap = true, iCanHasFlavor = true ) ) } private fun appWatcher(config: Config = LeakCanary.config): AppWatcher { val observer = AndroidDisplayLeakInterceptor { // 自定义处理泄漏结果 } return AppWatcher( config = config, leakInterceptor = observer, reachabilityInspector = AndroidObjectInspectors.appDefault ) } }
- 自定义配置