文章目录
说明
这是最近在了解 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.*
包下
上面就是所有翻译后的内容,希望对各位同学有所帮助。
技术永不眠,我们下期见!