认识LeakCanray 🐤 不需要手动初始化的秘密
前言
需要初始化的版本中,我们需要在application中初始化leakcanary,为什么新版本的leakcanary不需要了呢?本文带你探究
什么是LeakCanray
LeakCanary is a memory leak detection library for Android.
LeakCanary’s knowledge of the internals of the Android Framework gives it a unique ability to narrow down the cause of each leak, helping developers dramatically reduce Application Not Responding freezes and OutOfMemoryError crashes.
LeakCanary是一个适用于Android的内存泄漏检测库。
LeakCanary对安卓框架内部的了解使其能够独特地缩小每次泄漏的原因,帮助开发人员显著减少应用程序未响应冻结和OutOfMemoryError崩溃。
A small leak will sink a great ship.” - Benjamin Franklin
“一个小漏洞会击沉一艘大船。”-本杰明·富兰克林
摘录翻译自 LeakCanray官网
最新使用
在app的 build.gradle中添加
//leakcanary内存泄漏检测
debugImplementation "com.squareup.leakcanary:leakcanary-android:$version"
- $version是版本号
在2.0版本过后,不需要添加多余的代码,就这样就好了
为什么
需要初始化的版本
需要初始化的版本中,我们需要在application中初始化leakcanary
不需要初始化的版本
这需要对APP的启动流程中去寻找答案。在APP启动过程中,ActivityThread会收到一 “BIND_APPLICATION” 的消息,收到这条消息后在handleMessage进行处理,执行handleBindApplication方法,源码如下
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
//这个方法
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
......
}
通过这个方法调用了mInstrumentation.callApplicationOnCreate(app);,源码如下
...
try {
//调用application的oncreate
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
...
源码的注释
而在这之前,会先执行installContentProviders方法
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
...
ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
...
在其中执行了installProvider方法
通过这个方法,初始化ContentProvider。
讲了那么多,我们就可以说结论了,LeakCanray通过以上的流程,通过继承ContentProvider,在ContentProvider的onCreate方法中进行了初始化
2.0后不同版本实现的细微差别
初始化类的名字发生了改变
- 在2.0版本中初始化源码为
internal class LeakSentryInstaller : ContentProvider() {
override fun onCreate(): Boolean {
CanaryLog.logger = DefaultCanaryLog()
val application = context!!.applicationContext as Application
InternalLeakSentry.install(application)
return true
}
}
在2.7版本中初始化源码为
/**
* Content providers are loaded before the application class is created. [AppWatcherInstaller] is
* used to install [leakcanary.AppWatcher] on application start.
*/
internal sealed class AppWatcherInstaller : ContentProvider() {
/**
* [MainProcess] automatically sets up the LeakCanary code that runs in the main app process.
*/
internal class MainProcess : AppWatcherInstaller()
/**
* When using the `leakcanary-android-process` artifact instead of `leakcanary-android`,
* [LeakCanaryProcess] automatically sets up the LeakCanary code
*/
internal class LeakCanaryProcess : AppWatcherInstaller()
override fun onCreate(): Boolean {
val application = context!!.applicationContext as Application
AppWatcher.manualInstall(application)
return true
}
总结
主要是考察的其实是通过对LeakCanray源码的熟悉程度考察APP的启动流程,掌握这两个知识点那么LeakCanray不需要手动初始化的秘密对你来说就不是秘密啦