最近LeakCanary做了更新,釋出了2.0版本,帶了了很多性能上的優化,不過一個很吸引我的點在于,他居然不像以前一樣,需要手動初始化了。
按照以前的使用流程,一般我們都是在dependencies 加入依賴
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裡面加入初始化的邏輯。
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居然可以不再需要寫這個操作,隻需要在代碼裡面加入這麼一句依賴就可以了
dependencies {
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-alpha-1'
}
我有點懷疑自己的眼睛,重新看了下他們的Readme,是不是真的
Getting started Add LeakCanary to your
build.gradle:
dependencies { debugImplementation com.squareup.leakcanary:leakcanary-android:2.0-alpha-1' }
You’re good to go! LeakCanary will automatically show a notification when an activity or fragment memory leak is detected in
your debug build.
好吧,确實是這樣,那麼到底怎麼做到的?很神奇啊,這怎麼也會有一個地方會需要初始化的,到底換到那裡去了?
在經過對源碼的解讀後,發現了一個騷操作,感覺傳開後,以後的sdk庫都可能這麼做,教壞小朋友了。
ContentProvider
在經過對源碼的閱讀後,發現其實人家是基于CP這個對于絕大數開發來說,基本沒用到的四大元件之一來做的,真的是服了哈哈。檢視他的
leakcanary-leaksentry
子產品的
AndroidManifest.xml
檔案,可以看到下面的内容:
<?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操作,全是空的,就純粹利用系統會回調這個接口來做初始化,幫助開發偷懶,省去調用寫初始化邏輯。
個人看待這個,覺得得分兩部門
好處:确實帶來了
"免侵入"
,不需要業務人員寫任何代碼。
壞處:這有點把CP給用歪了。以後所有人都這麼弄,接入的sdk都這麼寫的話,那就真的可愛了。
ref
- https://github.com/square/leakcanary/wiki/Migrating-to-LeakCanary-2.0