V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
alalalizy
V2EX  ›  Android

安卓新手,内存泄漏问题

  •  
  •   alalalizy · 2021-07-26 15:03:59 +08:00 · 8970 次点击
    这是一个创建于 1210 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题描述

    • 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  
       2021-07-27 09:48:42 +08:00
    要么,在 A 的 onDestroyView() 中销毁 LinearLayout 的实例,要么把 replace 换成 show & hide
    JellyBeanX
        2
    JellyBeanX  
       2021-07-27 10:43:08 +08:00
    @JellyBeanX 说错了,是销毁持有 linearLayout 实例的对象
    ukyoo
        3
    ukyoo  
       2021-07-29 16:08:15 +08:00
    onDestroyView()后要手动把成员变量的 View 置空, 因为下一次 onCreateView()还会重新 infalte 一次布局, 这个成员变量就没什么用了, 视为泄露. https://www.jianshu.com/p/15ad41477f34
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3931 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 05:10 · PVG 13:10 · LAX 21:10 · JFK 00:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.