Principle analysis of Android's LeakCanary

Scenario: latest leakCanary2.8.1:

debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'

Principle: First of all, we are introducing the latest dependency package, and we don’t need to do anything, because its initialization registers contentProvider() in the manifest file, and puts the initialization in onCreate() to initialize. During the initialization process In it, he will use application to monitor and observe the changes in the life cycle of objects such as activity and fragment. When the life cycle of destruction is executed, he will use the corresponding ActivityWatch--->ObjectWatch to observe your destroyed object, so how to observe it? ? Add the object to the weak reference object, and bind this weak reference to a reference queue Queue (at the same time, add this weak reference to a map observation list first), so that when active Gc, if there is no leak, it will The activity observation object will be recycled, and this weak reference will be added to the reference queue. We can judge whether the reference queue has a value. If it is leaked, the weak reference of the leaked object will be added to a set collection called retained objects. Finally, the shark library (originally the haha ​​analysis library) will be used to query the leaked place to generate a dump file, and the analysis result will be notified to the developer. By.

Notification Click: Notify retained objects---click -->Dumping Heap---automatic -->Analyzing heap

How to see the results of this analysis:

 The above two figures are the reference chain relationship of the leaked object, and finally there is the leaked object LoginActivity, so why the leak has to be searched up, and it is found that the context (that is, the LoginActivity object) is held in the Dialog singleton, and it is gone in time Destory will not destroy this object, because it is always held by GcRoot.

 Here is the code causing the memory leak:

object LoadingDialog {


    //内部生成的时候,根据INSTANCE 看起来感觉是静态,因为可以LoadingDialog.show()
    //其实是伪静态
    fun show() {

    }

    //这种写法才是静态方法
    @JvmStatic
    fun show2() {

    }

    private var dialog:Dialog?=null

    fun show(context: Context) {

        cancel()
        dialog = Dialog(context)
        dialog?.setContentView(R.layout.dialog_loading)
        dialog?.setCancelable(false)
        dialog?.setCanceledOnTouchOutside(false)
        dialog?.show()

    }

    fun cancel() {
        dialog?.dismiss()
    }

}

The solution is to set the dialog to null when it is used up

fun cancel() {
        dialog?.dismiss()
        dialog = null;
    }

In this way leakCanary will not notify the leak point.

Guess you like

Origin blog.csdn.net/sunbinkang/article/details/122951794
Recommended