Android Canary泄漏-结算和ViewBinding

问题描述

我将LeakCanary导入到我的项目中,以了解我内部有哪些内存泄漏以及有多少内存泄漏,然后可以对其进行修复。我注意到这两个我无法修复。更好的说,我不知道如何使用代码解决它们。有人知道如何给我一些建议吗?

LeakCanary: 2 APPLICATION LEAKS
LeakCanary: References underlined with "~~~" are likely causes.
LeakCanary: Learn more at https://squ.re/leaks.
LeakCanary: 16523886 bytes retained by leaking objects
LeakCanary: Signature: 4594f3337285a2a3dd854a7bf9c944f5598ae18b
LeakCanary: ┬───
LeakCanary: │ GC Root: Global variable in native code
LeakCanary: │
LeakCanary: ├─ android.app.LoadedApk$Servicedispatcher$DeathMonitor instance
LeakCanary: │    Leaking: UNKNowN
LeakCanary: │    Retaining 144 bytes in 4 objects
LeakCanary: │    ↓ LoadedApk$Servicedispatcher$DeathMonitor.this$0
LeakCanary: │                                               ~~~~~~
LeakCanary: ├─ android.app.LoadedApk$Servicedispatcher instance
LeakCanary: │    Leaking: UNKNowN
LeakCanary: │    Retaining 622 bytes in 8 objects
LeakCanary: │    mContext instance of com.example.packagename.ApplicationContext
LeakCanary: │    ↓ LoadedApk$Servicedispatcher.mConnection
LeakCanary: │                                  ~~~~~~~~~~~
LeakCanary: ├─ com.android.billingclient.api.BillingClientImpl$zza instance
LeakCanary: │    Leaking: UNKNowN
LeakCanary: │    Retaining 41 bytes in 3 objects
LeakCanary: │    ↓ BillingClientImpl$zza.zzd
LeakCanary: │                            ~~~
LeakCanary: ├─ com.example.packagename.fragments.ShopFragment$setupBillingClient$1 instance
LeakCanary: │    Leaking: UNKNowN
LeakCanary: │    Retaining 12 bytes in 1 objects
LeakCanary: │    Anonymous class implementing com.android.billingclient.api.BillingClientStateListener
LeakCanary: │    ↓ ShopFragment$setupBillingClient$1.this$0
LeakCanary: │                                        ~~~~~~
LeakCanary: ╰→ com.example.packagename.fragments.ShopFragment instance
LeakCanary: ​     Leaking: YES (ObjectWatcher was watching this because com.example.packagename.fragments.ShopFragment received
LeakCanary: ​     Fragment#onDestroy() callback and Fragment#mFragmentManager is null)
LeakCanary: ​     Retaining 16523886 bytes in 33489 objects
LeakCanary: ​     key = b2ebfeff-4177-4587-b7f5-e4c89bc4afaa
LeakCanary: ​     watchDurationMillis = 40425
LeakCanary: ​     retainedDurationMillis = 35424
LeakCanary: 2804 bytes retained by leaking objects
LeakCanary: Signature: 71c80305d50d16354a6bec910e7f529c72e4296
LeakCanary: ┬───
LeakCanary: │ GC Root: Local variable in native code
LeakCanary: │
LeakCanary: ├─ android.os.HandlerThread instance
LeakCanary: │    Leaking: NO (PathClassLoader↓ is not leaking)
LeakCanary: │    Thread name: 'queued-work-looper'
LeakCanary: │    ↓ HandlerThread.contextClassLoader
LeakCanary: ├─ dalvik.system.PathClassLoader instance
LeakCanary: │    Leaking: NO (ViewDataBinding↓ is not leaking and A ClassLoader is never leaking)
LeakCanary: │    ↓ PathClassLoader.runtimeInternalObjects
LeakCanary: ├─ java.lang.Object[] array
LeakCanary: │    Leaking: NO (ViewDataBinding↓ is not leaking)
LeakCanary: │    ↓ Object[].[881]
LeakCanary: ├─ androidx.databinding.ViewDataBinding class
LeakCanary: │    Leaking: NO (a class is never leaking)
LeakCanary: │    ↓ static ViewDataBinding.sReferenceQueue
LeakCanary: │                             ~~~~~~~~~~~~~~~
LeakCanary: ├─ java.lang.ref.ReferenceQueue instance
LeakCanary: │    Leaking: UNKNowN
LeakCanary: │    Retaining 724 bytes in 30 objects
LeakCanary: │    ↓ ReferenceQueue.head
LeakCanary: │                     ~~~~
LeakCanary: ├─ androidx.databinding.ViewDataBinding$WeakListener instance
LeakCanary: │    Leaking: UNKNowN
LeakCanary: │    Retaining 52 bytes in 2 objects
LeakCanary: │    ↓ ViewDataBinding$WeakListener.mObservable
LeakCanary: │                                   ~~~~~~~~~~~
LeakCanary: ├─ androidx.databinding.ViewDataBinding$LiveDataListener instance
LeakCanary: │    Leaking: UNKNowN
LeakCanary: │    Retaining 16 bytes in 1 objects
LeakCanary: │    ↓ ViewDataBinding$LiveDataListener.mLifecycleOwner
LeakCanary: │                                       ~~~~~~~~~~~~~~~
LeakCanary: ╰→ com.example.packagename.fragments.InventoryFragment instance
LeakCanary: ​     Leaking: YES (ObjectWatcher was watching this because com.example.packagename.fragments.InventoryFragment
LeakCanary: ​     received Fragment#onDestroy() callback and Fragment#mFragmentManager is null)

如您所见,主要有2个泄漏,但是我不确定是否知道如何解决

解决方法

第一个泄漏跟踪显示ShopFragment可能通过调用BillingClientStateListenerShopFragment$setupBillingClient中设置了BillingClient#startConnection()。匿名类中的BillingClientStateListener实现,并且引用了其外部类的实例ShopFragment。看Javadoc,看来您需要在完成后即在片段被销毁后调用BillingClient#endConnection()。帐单documentation完全没有提及这一点,因此您可能要提交文档错误。

第二个泄漏跟踪显示与被破坏的InventoryFragment相关的ViewDataBinding.LiveDataListenerViewDataBinding.sReferenceQueue保留在内存中(请参阅sources hereViewDataBinding$WeakListener在队列中的事实表示ViewDataBinding.WeakListener不可强行到达。ViewDataBinding. processReferenceQueue()负责执行此操作,因此好像它已经有一段时间没有被调用了。很难确定没有堆转储,但是这看起来像是DataBinding库错误,您应该提交票证。