问题描述

  • A = 主页面 fragment
  • B = 输入内容页 fragment
  • C = 检索结果页 fragment 我在 A 中进行 replace 跳转到一个 B,完成输入后 replace 跳转到 C,此时使用 home 键进入后台运行,发生内存泄漏问题

报错情况

D/HomePageFragment: BaseFragment-->onPause()
D/DiscoveryFragment: BaseFragment-->onPause()
D/TvItemsFragment: BaseFragment-->onPause()
D/MainActivity: BaseActivity-->onPause()
D/LeakCanary: Scheduling check for retained objects in 5000ms because app became invisible
D/HomePageFragment: BaseFragment-->onStop()
D/DiscoveryFragment: BaseFragment-->onStop()
D/CommendFragment: BaseFragment-->onStop()
D/TvItemsFragment: BaseFragment-->onStop()
D/MainActivity: BaseActivity-->onStop()
D/MainActivity: BaseActivity-->onSaveInstanceState()

D/LeakCanary: ====================================
    HEAP ANALYSIS RESULT
    ====================================
    1 APPLICATION LEAKS
    
    References underlined with "~~~" are likely causes.
    Learn more at https://squ.re/leaks.
    
    53078 bytes retained by leaking objects
    Signature: b01ba777d9ce636d68e71237f54fafe95ee827f8
    ┬───
    │ 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 (ViewRootImpl↓ is not leaking and InputMethodManager is a singleton)
    │    ↓ InputMethodManager.mCurRootView
    ├─ android.view.ViewRootImpl instance
    │    Leaking: NO (ViewPager2$RecyclerViewImpl↓ is not leaking and ViewRootImpl#mView is not null)
    │    ↓ ViewRootImpl.mImeFocusController
    ├─ android.view.ImeFocusController instance
    │    Leaking: NO (ViewPager2$RecyclerViewImpl↓ is not leaking)
    │    ↓ ImeFocusController.mNextServedView
    ├─ androidx.viewpager2.widget.ViewPager2$RecyclerViewImpl instance
    │    Leaking: NO (SearchFragment↓ is not leaking and View attached)
    │    mContext instance of com.moviemore.android.ui.MainActivity with mDestroyed = false
    │    View.parent androidx.viewpager2.widget.ViewPager2 attached as well
    │    View#mParent is set
    │    View#mAttachInfo is not null (view attached)
    │    View.mID = R.id.null
    │    View.mWindowAttachCount = 1
    │    ↓ ViewPager2$RecyclerViewImpl.mAdapter
    ├─ com.moviemore.android.ui.common.ui.BaseViewPagerFragment$VpAdapter instance
    │    Leaking: NO (SearchFragment↓ is not leaking)
    │    ↓ BaseViewPagerFragment$VpAdapter.mFragmentManager
    ├─ androidx.fragment.app.FragmentManagerImpl instance
    │    Leaking: NO (SearchFragment↓ is not leaking)
    │    ↓ FragmentManagerImpl.mFragmentStore
    ├─ androidx.fragment.app.FragmentStore instance
    │    Leaking: NO (SearchFragment↓ is not leaking)
    │    ↓ FragmentStore.mActive
    ├─ java.util.HashMap instance
    │    Leaking: NO (SearchFragment↓ is not leaking)
    │    ↓ HashMap.table
    ├─ java.util.HashMap$Node[] array
    │    Leaking: NO (SearchFragment↓ is not leaking)
    │    ↓ HashMap$Node[].[6]
    ├─ java.util.HashMap$Node instance
    │    Leaking: NO (SearchFragment↓ is not leaking)
    │    ↓ HashMap$Node.value
    ├─ androidx.fragment.app.FragmentStateManager instance
    │    Leaking: NO (SearchFragment↓ is not leaking)
    │    ↓ FragmentStateManager.mFragment
    ├─ com.moviemore.android.ui.search.SearchFragment instance
    │    Leaking: NO (Fragment#mFragmentManager is not null)
    │    ↓ SearchFragment.rootView
    │                     ~~~~~~~~
    ╰→ android.widget.LinearLayout instance
    ​     Leaking: YES (ObjectWatcher was watching this because com.moviemore.android.ui.search.SearchFragment received Fragment#onDestroyView() callback (references to its views should be cleared to prevent leaks))
    ​     key = 888671cb-ecda-4776-b4dd-b4f2350acb32
    ​     watchDurationMillis = 7210
    ​     retainedDurationMillis = 2208
    ​     mContext instance of com.moviemore.android.ui.MainActivity with mDestroyed = false
    ​     View#mParent is null
    ​     View#mAttachInfo is null (view detached)
    ​     View.mWindowAttachCount = 1
    ====================================
    0 LIBRARY LEAKS

3 条回复    2021-07-29 16:08:15 +08:00

JellyBeanX
    1

JellyBeanX   2 天前

要么,在 A 的 onDestroyView() 中销毁 LinearLayout 的实例,要么把 replace 换成 show & hide
JellyBeanX
    2

JellyBeanX   2 天前

@JellyBeanX 说错了,是销毁持有 linearLayout 实例的对象
ukyoo
    3

ukyoo   59 分钟前

onDestroyView()后要手动把成员变量的 View 置空, 因为下一次 onCreateView()还会重新 infalte 一次布局, 这个成员变量就没什么用了, 视为泄露