LeakCanary2的免寫 初始化代碼 原理

最近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' }ide

You'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庫均可能這麼作,教壞小朋友了。優化

ContentProvider

在通過對源碼的閱讀後,發現其實人家是基於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都這麼寫的話,那就真的可愛了。

ref

  1. github.com/square/leak…
相關文章
相關標籤/搜索