Yesterday’s question mentioned some points to note about memory leaks. At the end of the article, it says that LeakCanary detects memory leaks. In fact, I’m sure most of you know or even use this library.

This series usually if found a good resource, will choose to directly intercept the part, so the reference link at the bottom of the article is generally very good, you can directly go to see yo ~

What is the basic workflow of LeakCanary?

To use LeakCanary, simply write the dependency in build.gradle and register with the Application class.

Of course, you only need to register this operation in the Application for the 1.x version that most people are exposed to, and in fact LeakCanary has now been upgraded to 2.x, where the code is less invasive and Kotlin pure. Kotlin is becoming more and more important in Android development, as evidenced by the use of Kotlin in various Google demos and the use of Kotlin in various mainstream libraries. If you don’t use Kotlin, you have to learn a lot about it.

For the working principle, I believe that you should also have more or less a certain understanding, here just happens to have a very good flow chart directly borrowed, in addition, he understands LeakCanary from the source point of view of this article is also written very good, interested click the link at the bottom of the article directly.

First time using LeakCanary why is there no Icon entry

When using LeakCanary, we often find that the Launcher icon of LeakCanary does not appear at the beginning, but when there is a memory leak warning, there is such an icon on the system desktop, which is usually very curious.

A clue can be seen from the 1.x source code. In leakcanary- Android’s manifast, we can see the configuration:

<! --leakcanary-sample/src/main/AndroidManifest.xml-->
<service
    android:name=".internal.HeapAnalyzerService"
    android:process=":leakcanary"
    android:enabled="false"
    />
<service
    android:name=".DisplayLeakService"
    android:process=":leakcanary"
    android:enabled="false"
    />
<activity
    android:theme="@style/leak_canary_LeakCanary.Base"
    android:name=".internal.DisplayLeakActivity"
    android:process=":leakcanary"
    android:enabled="false"
    android:label="@string/leak_canary_display_activity_label"
    android:icon="@mipmap/leak_canary_icon"
    android:taskAffinity="com.squareup.leakcanary.${applicationId}"
    >
  <intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.LAUNCHER"/>
  </intent-filter>
</activity>
Copy the code

We can see that the DisplayLeakActivity is set to the Launcher with the corresponding Icon, so using LeakCanary will generate an Icon entry on the system desktop. However, the Enable property of DisplayLeakActivity is false by default, so the entry will not be displayed on the desktop. In the event of a memory leak, LeakCanary automatically sets the Enable property to true.

What has LeakCanary 2 done

Recently, LeakCanary has been upgraded to version 2.x, which is a complete refactor to remove the empty package referenced in the 1.x release leakcanary-Android-no-op. And Kotlin language coverage is up to 99.8%, there is no need to do the following code in the Application.

//com.example.leakcanary.ExampleApplication
@Override
public void onCreate(a) {
    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);
}
Copy the code

Just add such code to the dependency.

dependencies {
  debugImplementation 'com. Squareup. Leakcanary: leakcanary - android: 2.0 - alpha - 2'
}
Copy the code

See this operation for the first time, will feel very magical, carefully read the source code to find that it should use a SAO operation: ContentProvider.

This can be seen in the Androidmanifest.xml file of the Leakcancanary – Leaksentry module:

<?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>

Copy the code

After further checking LeakSentryInstaller you can see:

package leakcanary.internal

import android.app.Application
import android.content.ContentProvider
import android.content.ContentValues
import android.database.Cursor
import android.net.Uri
import leakcanary.CanaryLog

/** * Content providers are loaded before the application class is created. [LeakSentryInstaller] is * used to install [leaksentry.LeakSentry] on application start. */
internal class LeakSentryInstaller : ContentProvider() {

  override fun onCreate(a): Boolean {
    CanaryLog.logger = DefaultCanaryLog()
    valapplication = context!! .applicationContextas Application
    InternalLeakSentry.install(application)
    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}}Copy the code

LeakCanary does this because we know that ContentProvider onCreate() is called between Application attachBaseContext() and onCreate(). It is very convenient to keep the init logic inside the library so that the caller does not need to initialize it in the Application at all. This will not only avoid errors caused by developers forgetting to initialize, but also make our massive Application code simpler.

Reference: www.jianshu.com/p/49239eac7…