シナリオ: 最新の leakCanary2.8.1:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'
原則: まず第一に、最新の依存関係パッケージを導入しており、その初期化により contentProvider() がマニフェスト ファイルに登録され、初期化が onCreate() に入れられて初期化されるため、何もする必要はありません。プロセス その中で、彼はアプリケーションを使用して、アクティビティやフラグメントなどのオブジェクトのライフサイクルの変化を監視および観察します. 破壊のライフサイクルが実行されると、対応する ActivityWatch--->ObjectWatch を使用して、破壊されたオブジェクトを観察します.天体だからどうやって観察するの??オブジェクトを弱参照オブジェクトに追加し、この弱参照を参照キュー Queue にバインドします (同時に、この弱参照を最初にマップ観測リストに追加します)。これにより、Gc がアクティブなときにリークがなければ、アクティビティ観測オブジェクトはリサイクルされ、この弱参照は参照キューに追加されます. 参照キューに値があるかどうかを判断できます. リークされている場合は、リークされたオブジェクトの弱参照がセットに追加されます.保持オブジェクトと呼ばれるコレクション. 最後に、shark ライブラリ (元は haha 分析ライブラリ) を使用して、リークされた場所をクエリしてダンプ ファイルを生成し、分析結果を開発者に通知します。
通知 クリック: 保持されたオブジェクトを通知 ---クリック --> ヒープのダンプ --- 自動 --> ヒープの分析中
この分析結果の表示方法:
上の2つの図はリークしたオブジェクトの参照連鎖関係で、最後にリークしたオブジェクトLoginActivityがあるので、なぜリークを調べなければならないのか、コンテキスト(つまりLoginActivityオブジェクト)が保持されていることがわかります。このオブジェクトは常に GcRoot によって保持されているため、Destory はこのオブジェクトを破棄しません。
メモリリークの原因となっているコードは次のとおりです。
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()
}
}
解決策は、ダイアログが使い果たされたときにダイアログを null に設定することです
fun cancel() {
dialog?.dismiss()
dialog = null;
}
このように、leakCanary はリークポイントを通知しません。