文章目錄
說明
這是最近在瞭解 LeakCanary 內存泄漏分析工具使用時看到的一篇文章,講的是升級到 LeakCanary 2 的一些操作或者說明。
這是一篇譯文,僅僅是針對英語不太好的同學,其實我英語也一般,所以譯文中有翻譯的不正確的地方,希望同學們能輕噴!
這是一篇譯文!針對的是對 LeakCanary 有一定了解的同學。
如果同學們一點都不瞭解的可以通過下面的鏈接先進行相關了解:
原文鏈接
譯文
升級到 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
,我如何確保在發佈構建期間不運行這些操作? - 回答:只要你添加了
debugImplementation
爲leakcanary-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.*
包下
上面就是所有翻譯後的內容,希望對各位同學有所幫助。
技術永不眠,我們下期見!