【问题标题】:Memory Leak detected by LeakCanary on Activity with FragmentsLeakCanary 在带有片段的活动上检测到内存泄漏
【发布时间】:2021-02-12 17:08:29
【问题描述】:

我们在 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/ 捕获了它 我注意到如果我们更改所有“替换”以添加 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 次泄漏的原因。 真的是泄密吗? 任何信息将不胜感激。

【问题讨论】:

  • 您使用的是什么版本的导航?你有filed an issue against Navigation吗?
  • 你的意思是``` // 导航库 def nav_version = "2.2.2" implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-ui -ktx:$nav_version" ```

标签: android android-fragments memory-leaks leakcanary


【解决方案1】:

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

【讨论】:

  • 谢谢。这行得通,我已经验证过了。但是,我坚持使用androidx.constraintlayout.widget.ConstraintLayout,因为我不需要androidx.fragment.app.FragmentContainerView。我缺少什么优势吗?
  • 是的,您应该始终使用FragmentContainerView。正如this comment 中所述,FragmentContainerView 修复了当片段的根布局在其他布局中的方向时出现的窗口插入和布局问题,此外还可以仅在 XML 中创建和设置片段。
【解决方案2】:

我已经修复了内存泄漏。

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

相反,我使用了 ConstraintLayout。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 2015-08-04
    相关资源
    最近更新 更多