升級到 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.* 包下


上面就是所有翻譯後的內容,希望對各位同學有所幫助。

技術永不眠,我們下期見!

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