LeakCanary 在 Activity 上使用 Fragments 检测到内存泄漏

Memory Leak detected by LeakCanary on Activity with Fragments

我们在 2.0 版 $ git clone https://source.codeaurora.org/quic/la/camera-samples -b iot-concam-apk.lnx.1.1 中有 2 个明显的内存泄漏(看起来相同),它们会在应用程序关闭时消失。

它们在应用程序启动后立即发生。 一次又一次地切换选项卡不会增加泄漏的数量,我认为这是一件好事。

我用 https://square.github.io/leakcanary/getting_started/ 抓到了它 我注意到如果我们更改所有 'replace' 以在 onCreate 中添加,则 2 次泄漏发生在 Tab 开关上而不是应用程序启动时。

2021-01-28 09:21:41.781 28582-28582/com.android.example.camera2.video D/LeakCanary: 
    ┬───
    │ GC Root: System class
    │
    ├─ android.view.inputmethod.InputMethodManager class
    │    Leaking: NO (InputMethodManager↓ is not leaking and a class is never leaking)
    │    ↓ static InputMethodManager.sInstance
    ├─ android.view.inputmethod.InputMethodManager instance
    │    Leaking: NO (DecorView↓ is not leaking and InputMethodManager is a singleton)
    │    ↓ InputMethodManager.mCurRootView
    ├─ com.android.internal.policy.DecorView instance
    │    Leaking: NO (LinearLayout↓ is not leaking and View attached)
    │    View is part of a window view hierarchy
    │    View.mAttachInfo is not null (view attached)
    │    View.mWindowAttachCount = 1
    │    mContext instance of com.android.internal.policy.DecorContext, wrapping activity com.example.android.camera2.video.
    │    CameraActivity with mDestroyed = false
    │    ↓ DecorView.mContentRoot
    ├─ android.widget.LinearLayout instance
    │    Leaking: NO (CameraActivity↓ is not leaking and View attached)
    │    View is part of a window view hierarchy
    │    View.mAttachInfo is not null (view attached)
    │    View.mWindowAttachCount = 1
    │    mContext instance of com.example.android.camera2.video.CameraActivity with mDestroyed = false
    │    ↓ View.mContext
    ├─ com.example.android.camera2.video.CameraActivity instance
    │    Leaking: NO (FragmentContainerView↓ is not leaking and Activity#mDestroyed is false)
    │    mApplication instance of android.app.Application
    │    mBase instance of android.app.ContextImpl
    │    ↓ CameraActivity.container
    ├─ androidx.fragment.app.FragmentContainerView instance
    │    Leaking: NO (View attached)
    │    View is part of a window view hierarchy
    │    View.mAttachInfo is not null (view attached)
    │    View.mID = R.id.fragment_container
    │    View.mWindowAttachCount = 1
    │    mContext instance of com.example.android.camera2.video.CameraActivity with mDestroyed = false
    │    ↓ View.mKeyedTags
    │           ~~~~~~~~~~
    ├─ android.util.SparseArray instance
    │    Leaking: UNKNOWN
    │    Retaining 3.1 kB in 117 objects
    │    ↓ SparseArray.mValues
    │                  ~~~~~~~
    ├─ java.lang.Object[] array
    │    Leaking: UNKNOWN
    │    Retaining 3.1 kB in 115 objects
    │    ↓ Object[].[0]
    │               ~~~
    ├─ androidx.navigation.NavHostController instance
    │    Leaking: UNKNOWN
    │    Retaining 3.1 kB in 114 objects
    │    mActivity instance of com.example.android.camera2.video.CameraActivity with mDestroyed = false
    │    mContext instance of com.example.android.camera2.video.CameraActivity with mDestroyed = false
    │    ↓ NavController.mLifecycleOwner
    │                    ~~~~~~~~~~~~~~~
    ╰→ androidx.navigation.fragment.NavHostFragment instance
         Leaking: YES (ObjectWatcher was watching this because androidx.navigation.fragment.NavHostFragment received
         Fragment#onDestroy() callback and Fragment#mFragmentManager is null)
         Retaining 1.7 kB in 57 objects
         key = 1350d8e9-4d31-42de-9bff-693ddce5f5ef
         watchDurationMillis = 16748
         retainedDurationMillis = 11748
   
    METADATA
   
    Build.VERSION.SDK_INT: 29
    Build.MANUFACTURER: QUALCOMM
    LeakCanary version: 2.6
    App process name: com.android.example.camera2.video
    Stats: LruCache[maxSize=3000,hits=2630,misses=44837,hitRate=5%]
    RandomAccess[bytes=2279092,reads=44837,travel=13095741867,range=14884449,size=19192832]
    Heap dump reason: user request
    Analysis duration: 5510 ms

由于泄漏的数量没有增加,并且它们在应用程序关闭时消失,我想我们可以顺其自然,但我仍然无法找到 2 次泄漏的原因。 真的是漏电吗? 任何信息将不胜感激。

我已经修复了内存泄漏问题。

在我的 XML 中不使用 androidx.fragment.app.FragmentContainerView 是解决方案。

相反,我使用了 ConstraintLayout。

如果您不在 XML 中使用 app:navGraph="@navigation/nav_graph" 控制片段,而是在 activity[=13= 中使用 replace<CameraFragmentSnapshot>(R.id.fragment_container, null, null),我认为您不应该使用它]

您正在点击 this issue,这是针对 Navigation 2.2.3 或更高版本修复的。请升级到最新稳定版本的Navigation (2.3.3) 来解决这个问题。