zeitgeist
zeitgeist

Reputation: 1032

Memory Leak detected by LeakCanary on Activity with Fragments

We have 2 distinct memory leaks(which look the same) in $ git clone https://source.codeaurora.org/quic/la/camera-samples -b iot-concam-apk.lnx.1.1 in version 2.0 and they go away on app close.

They occurs as soon as the app is launched. Switching tabs, again and again, does not increase the number of leaks which is a good thing I think.

I caught it using https://square.github.io/leakcanary/getting_started/ I noticed if we change all 'replace' to add in onCreate, the 2 leaks happen on Tab switch and not on the app launch.

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

Since the number of leaks does not increase and they go away on app close I think we can let it be but still, I have been unable to find the cause of the 2 leaks. Is it really a leak? Any info would be appreciated.

Upvotes: 0

Views: 2271

Answers (2)

ianhanniballake
ianhanniballake

Reputation: 199825

You are hitting this issue, which is fixed for Navigation 2.2.3 or higher. Please upgrade to the latest stable version of Navigation (2.3.3) to fix this issue.

Upvotes: 1

zeitgeist
zeitgeist

Reputation: 1032

I have fixed the memory leak.

Not using androidx.fragment.app.FragmentContainerView in my XML was the solution.

Instead, I have used a ConstraintLayout.

I think you should not use it if you do not control your fragment using app:navGraph="@navigation/nav_graph" in XML and instead use replace<CameraFragmentSnapshot>(R.id.fragment_container, null, null) in your activity

Upvotes: 0

Related Questions