시나리오: 최신 누출Canary2.8.1:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'
원칙: 우선 최신 종속성 패키지를 도입하고 있으며 초기화는 매니페스트 파일에 contentProvider()를 등록하고 onCreate()에 초기화를 넣어 초기화하기 때문에 아무것도 할 필요가 없습니다. 프로세스에서 그는 응용 프로그램을 사용하여 활동 및 프래그먼트와 같은 개체의 수명 주기 변화를 모니터링하고 관찰합니다.파괴 수명 주기가 실행되면 해당 ActivityWatch--->ObjectWatch를 사용하여 파괴된 것을 관찰합니다. 객체, 그래서 그것을 관찰하는 방법?? 개체를 약한 참조 개체에 추가하고 이 약한 참조를 참조 큐 Queue에 바인딩합니다(동시에 이 약한 참조를 맵 관찰 목록에 먼저 추가). 활성화된 Gc에서 누수가 없으면 활동 관찰 개체를 재활용하고 이 약한 참조를 참조 큐에 추가합니다. 참조 큐에 값이 있는지 여부를 판단할 수 있습니다. 누출된 경우 누출된 개체의 약한 참조가 집합에 추가됩니다. 마지막으로 상어 라이브러리(원래 하하 분석 라이브러리)를 이용해 유출된 장소를 쿼리해 덤프 파일을 생성하고 분석 결과를 개발자에게 알려준다.
알림 클릭: 보유 객체 알림---클릭 -->힙 덤프---자동 -->힙 분석 중
이 분석 결과를 보는 방법:
위의 두 그림은 누수 개체의 참조 체인 관계이며 마지막으로 누수 개체 LoginActivity가 있으므로 누수를 검색해야 하는 이유는 컨텍스트(즉, LoginActivity 개체)가 유지됨을 알 수 있습니다. Dialog 싱글톤에서 시간이 지남에 따라 사라집니다. Destory는 항상 GcRoot에 의해 유지되기 때문에 이 개체를 파괴하지 않습니다.
메모리 누수를 일으키는 코드는 다음과 같습니다.
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는 누출 지점을 알리지 않습니다.