升级到 LeakCanary 2 的一些说明与操作

说明

这是最近在了解 LeakCanary 内存泄漏分析工具使用时看到的一篇文章,讲的是升级到 LeakCanary 2 的一些操作或者说明。

这是一篇译文,仅仅是针对英语不太好的同学,其实我英语也一般,所以译文中有翻译的不正确的地方,希望同学们能轻喷!

这是一篇译文!针对的是对 LeakCanary 有一定了解的同学。

如果同学们一点都不了解的可以通过下面的链接先进行相关了解:

查内存泄漏神器,LeakCanray原来是这样工作的


原文链接

Upgrading to LeakCanary 2


译文

升级到 LeakCanary 2

LeakCanary 2 重写后的一些重要改变如下:

  • 新的 heap 分析器,重新的实现并节省了 10 倍的内存(see Shark
  • API 的更新用来简化配置,提供对新的 heap 分析器的访问
  • 内部重写全采用 Kotlin
  • 一次分析检测多个泄漏并按照泄漏的类型分组

依赖

原来

dependencies {
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
  releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
  // Optional, if you use support library fragments:
  debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.3'
}

现在

dependencies {
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.2'
}

一些注意项

  • leakcanary-android-no-op 项的配置不需要了,如果你有编译错误,请参考下面
  • 问题:如果不再有 no-op,我如何确保在发布构建期间不运行这些操作?
  • 回答:只要你添加了 debugImplementationleakcanary-android ,在你的发布版本中不会有任何引用 LeakCanary 的代码。
  • LeakCanary 不再依赖于 support Library,也不再依赖于 AndroidX。
  • 如果你有 AndroidX fragments 依赖,检测 AndroidX fragments 是自动的。

默认设置代码

原来

public class ExampleApplication extends Application {

  @Override public void onCreate() {
    super.onCreate();
    if (LeakCanary.isInAnalyzerProcess(this)) {
      // This process is dedicated to LeakCanary for heap analysis.
      // You should not init your app in this process.
      return;
    }
    LeakCanary.install(this);
    // Normal app init code...
  }
}

现在

默认设置 不需要额外的代码

一些注意项

  • LeakCanary 会自动安装
  • LeakCanary 分析现在在主进程中运行,因此不需要调用 LeakCanary. isinanalyzerprocess()

检索 RefWatcher

原来

val refWatcher: RefWatcher = LeakCanary.installedRefWatcher()

现在

ObjectWatcher objectWatcher = AppWatcher.INSTANCE.getObjectWatcher();

编译错误,因为在发布的代码中使用了 RefWatcher

如果您在非调试代码中使用 RefWatcher,您现在会得到一个编译错误,因为 no-op 项的配置已经不用了。ObjectWatcher 现在位于 object-watcher 配置项中并适用于生产环境。你有两个选择:

选项1:添加 object-watcher-android 来发布构建

dependencies {
  implementation 'com.squareup.leakcanary:leakcanary-object-watcher-android:2.2'
}
  • 它将自动保留您传递给 AppWatcher.objectWatcher 的已销毁 activities,fragments和任何实例 的一个弱引用
  • 不会触发 heap dumps 或者 LeakCanary 做的其他事情
  • 这是很少量的代码,应该不会对你的发布应用程序有任何影响
  • 你可以使用它来计数保留的对象,例如,添加 metadata 到 OutOfMemoryError crashes:
int retainedObjectCount = AppWatcher.INSTANCE.getObjectWatcher().getRetainedObjectCount();

选项2:创建自己的 ObjectWatcher 接口

// In shared code
interface MaybeObjectWatcher {
  fun watch(watchedObject: Any, description: String)

  object None : MaybeObjectWatcher {
    override fun watch(watchedObject: Any, description: String) {
    }
  }
}

// In debug code
class RealObjectWatcher : MaybeObjectWatcher {
  override fun watch(watchedObject: Any, description: String) {
    AppWatcher.objectWatcher.watch(watchedObject, description)
  }
}

发布代码中使用 MaybeObjectWatcher.None ,调试代码中使用 RealObjectWatcher


配置 LeakCanary

原来

public class DebugExampleApplication extends ExampleApplication {

  @Override protected void installLeakCanary() {
    RefWatcher refWatcher = LeakCanary.refWatcher(this)
      .watchActivities(false)
      .buildAndInstall();
  }
}

现在

AppWatcher 负责检测保留的对象。可以通过替换 AppWatcher.config 随时更新配置:

class DebugExampleApplication : ExampleApplication() {

  override fun onCreate() {
    super.onCreate()
    AppWatcher.config = AppWatcher.config.copy(watchFragmentViews = false)
  }
}

LeakCanary负责获取 heap dumps 并分析它们。它的配置可以通过替换 LeakCanary.config 随时更新:

disableLeakCanaryButton.setOnClickListener {
  LeakCanary.config = LeakCanary.config.copy(dumpHeap = false)
}

在 instrumentation tests 中运行 LeakCanary

原来

在你的 build.gradle 文件中:

dependencies {
  androidTestImplementation "com.squareup.leakcanary:leakcanary-android-instrumentation:${leakCanaryVersion}"
}

android {
  defaultConfig {
    // ...

    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    testInstrumentationRunnerArgument "listener", "com.squareup.leakcanary.FailTestOnLeakRunListener"
  }
}

在测试的 Application 类:

public class InstrumentationTestExampleApplication extends DebugExampleApplication {
  @Override protected void installLeakCanary() {
    InstrumentationLeakDetector.instrumentationRefWatcher(this)
      .buildAndInstall();
  }
}

现在

在你的 build.gradle 文件中:

dependencies {
  androidTestImplementation "com.squareup.leakcanary:leakcanary-android-instrumentation:${leakCanaryVersion}"
}

android {
  defaultConfig {
    // ...

    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    testInstrumentationRunnerArgument "listener", "leakcanary.FailTestOnLeakRunListener"
  }
}

不需要额外配置代码。


注册监听/上传到服务器

原来

public class LeakUploadService extends DisplayLeakService {
  @Override protected void afterDefaultHandling(HeapDump heapDump, AnalysisResult result, String leakInfo) {
    // TODO Upload result to server
  }
}
RefWatcher refWatcher = LeakCanary.refWatcher(this)
  .listenerServiceClass(LeakUploadService.class);
  .buildAndInstall();
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    >
  <application android:name="com.example.DebugExampleApplication">
    <service android:name="com.example.LeakUploadService" />
  </application>
</manifest>

现在

class LeakUploader : OnHeapAnalyzedListener {

  val defaultListener = DefaultOnHeapAnalyzedListener.create()

  override fun onHeapAnalyzed(heapAnalysis: HeapAnalysis) {
    TODO("Upload heap analysis to server")

    // Delegate to default behavior (notification and saving result)
    defaultListener.onHeapAnalyzed(heapAnalysis)
  }
}

class DebugExampleApplication : ExampleApplication() {

  override fun onCreate() {
    super.onCreate()
    LeakCanary.config = LeakCanary.config.copy(
        onHeapAnalyzedListener = LeakUploader()
    )
  }
}

匹配已知的 library 泄漏

原来

ExcludedRefs excludedRefs = AndroidExcludedRefs.createAppDefaults()
    .staticField("com.samsing.SomeSingleton", "sContext")
    .build();
RefWatcher refWatcher = LeakCanary.refWatcher(this)
  .excludedRefs(excludedRefs)
  .buildAndInstall();
}

现在

LeakCanary.config = LeakCanary.config.copy(
    referenceMatchers = AndroidReferenceMatchers.appDefaults +
        AndroidReferenceMatchers.staticFieldLeak(
            "com.samsing.SomeSingleton",
            "sContext"
        )
)

提示
没有与ExcludedRefs.Builder.clazz()相同的API,因为它导致了滥用。对应请看 Instead see Ignoring specific activities or fragment classes


公共 API 包

原来

所有公开的 APIs 位于 com.squareup.leakcanary.* 包下

现在

所有公开的 APIs 位于 leakcanary.* 包下


上面就是所有翻译后的内容,希望对各位同学有所帮助。

技术永不眠,我们下期见!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章