LeakCanary 2.0后 为什么不需要在application中调用install
用过 LeakCanary
的都知道,在版本2.0之前需要调用LeakCanary.install()
来开启组件的功能以便监听内存泄露。但是在2.0版本之后不需要手动调用了,直接依赖架包就可以使用leak的功能了。这是怎么做到的?难道Leak不需要初始化了?当然不是。要说清这个需要我们先来了解app的启动流程。
Application的启动流程
从图片我们分析app启动流程如下步骤
- 点击图片的时候
launch
进程通过binder
和AMS通信启动一个activity - AMS收到启动的消息后以
socket
的方式通信Zygote
进程fork一个app进程 - app进程启动后,创建
ActivityThread,Looper、Handler
对象,开启主线程消息循环Looper.loop()。 -
ActivityThread
通过AMS的代理对象ActivityManagerProxy
以binder的方式通信AMS - AMS接收到信息,调用attachApplication方法
- 在
AttachApplication
方法中,AMS分别通过bindApplication、scheduleLaunchActivity
方法,通知APP进程的主线程Handler,对APP进程的Application和Activity进行初始化,并执行Application、Activity的生命周期。
当Activity启动完成后,整个application的启动流程完毕。那么这跟我们的LeakCanary不主动初始化有什么关系呢?
不着急,关键就在bindApplication方法中。来看看bindApplication中的关键代码。
bindApplication中的关键代码
private void handleBindApplication(AppBindData data) {
VMRuntime.registerSensitiveThread();
//......... 省略中间代码
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
mInstrumentation.onCreate(data.instrumentationArgs);
} catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
//......... 省略后面的代码
}
仔细看这句代码mInstrumentation.callApplicationOnCreate(app)
其实最终调用到了Application
的onCreate
方法之中。往前看你会看到这样一句代码。installContentProviders(app, data.providers)
这句代码实现了ContentProviders
的安装,所以app定义的provider都是优先于application的oncreate执行的。
在LeakCanary2.0以后就把初始化方法放在了ContentProvider中。来看看这个provider的实现。
LeakCanary 的初始化位置
在LeakCanary2.0以后就把初始化方法放在了ContentProvider
中。来看看这个provider的实现。
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
}
//......省略其他代码
}
可以看到在onCreate中调用了AppWatcher.manualInstall()
来初始化LeakCanary