最近LeakCanary作了升级,发布了2.0版本,带了了不少性能上的优化,不过一个很吸引个人点在于,他竟然不像之前同样,须要手动初始化了。android
按照之前的使用流程,通常咱们都是在dependencies 加入依赖git
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'
}
复制代码
接着在咱们的application里面加入初始化的逻辑。github
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 2.0竟然能够再也不须要写这个操做,只须要在代码里面加入这么一句依赖就能够了bash
dependencies {
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-alpha-1'
}
复制代码
我有点怀疑本身的眼睛,从新看了下他们的Readme,是否是真的app
Getting started Add LeakCanary to your
build.gradle:
dependencies { debugImplementation com.squareup.leakcanary:leakcanary-android:2.0-alpha-1' }
ideYou're good to go! LeakCanary will automatically show a notification when an activity or fragment memory leak is detected in your debug build.性能
好吧,确实是这样,那么到底怎么作到的?很神奇啊,这怎么也会有一个地方会须要初始化的,到底换到那里去了?gradle
在通过对源码的解读后,发现了一个骚操做,感受传开后,之后的sdk库均可能这么作,教坏小朋友了。优化
在通过对源码的阅读后,发现其实人家是基于CP这个对于绝大数开发来讲,基本没用到的四大组件之一来作的,真的是服了哈哈。查看他的leakcanary-leaksentry
模块的AndroidManifest.xml
文件,能够看到下面的内容:ui
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.squareup.leakcanary.leaksentry"
>
<application>
<provider
android:name="leakcanary.internal.LeakSentryInstaller"
android:authorities="${applicationId}.leak-sentry-installer"
android:exported="false"/>
</application>
</manifest>
复制代码
接着咱们去看下那LeakSentryInstaller
这个类到底作了什么。
internal class LeakSentryInstaller : ContentProvider() {
override fun onCreate(): Boolean {
CanaryLog.logger = DefaultCanaryLog()
val application = context!!.applicationContext as Application
InternalLeakSentry.install(application)
//骚操做在这里,利用系统自动调用CP的onCreate方法来作初始化
return true
}
override fun query(
uri: Uri,
strings: Array<String>?,
s: String?,
strings1: Array<String>?,
s1: String?
): Cursor? {
return null
}
override fun getType(uri: Uri): String? {
return null
}
override fun insert(
uri: Uri,
contentValues: ContentValues?
): Uri? {
return null
}
override fun delete(
uri: Uri,
s: String?,
strings: Array<String>?
): Int {
return 0
}
override fun update(
uri: Uri,
contentValues: ContentValues?,
s: String?,
strings: Array<String>?
): Int {
return 0
}
}
复制代码
咱们看到这个CP类,没作任何的CURD操做,全是空的,就纯粹利用系统会回调这个接口来作初始化,帮助开发偷懒,省去调用写初始化逻辑。
我的看待这个,以为得分两部门 好处:确实带来了 "免侵入"
,不须要业务人员写任何代码。通常启动的顺序是 Application->attachBaseContext =====>ContentProvider->onCreate =====>Application->onCreate =====>Activity->onCreate
因此对于大多数场景,写在CP的初始化的实际是足够优先了!!
坏处:这有点把CP给用歪了。之后全部人都这么弄,接入的sdk都这么写的话,那就真的可爱了。