Anthony
Anthony

Reputation: 4049

Obscure leak found with Leak Canary in app that uses ToothPick

I have an app that is implemented with single Activity and with Toothpick / Ktp.

I create a scope for every fragment, that I close when the fragment is destroyed. This behavior is done in the BaseFragment Class.

It does use ViewBinding.

The adapter and its listener is nulled when the onDestroyedView is called.

Someone has other idea where this leak could come ? Or detail to search ?

┬───
│ GC Root: Global variable in native code
│
├─ toothpick.Toothpick class
│    Leaking: NO (HomeFragment↓ is not leaking and a class is never leaking)
│    ↓ static Toothpick.MAP_KEY_TO_SCOPE
├─ java.util.concurrent.ConcurrentHashMap instance
│    Leaking: NO (HomeFragment↓ is not leaking)
│    ↓ ConcurrentHashMap.table
├─ java.util.concurrent.ConcurrentHashMap$Node[] array
│    Leaking: NO (HomeFragment↓ is not leaking)
│    ↓ ConcurrentHashMap$Node[].[5]
├─ java.util.concurrent.ConcurrentHashMap$Node instance
│    Leaking: NO (HomeFragment↓ is not leaking)
│    ↓ ConcurrentHashMap$Node.key
├─ com.surprise.feature.home.presentation.HomeFragment instance
│    Leaking: NO (Fragment#mFragmentManager is not null)
│    ↓ HomeFragment.mLifecycleRegistry
│                   ~~~~~~~~~~~~~~~~~~
├─ androidx.lifecycle.LifecycleRegistry instance
│    Leaking: UNKNOWN
│    ↓ LifecycleRegistry.mObserverMap
│                        ~~~~~~~~~~~~
├─ androidx.arch.core.internal.FastSafeIterableMap instance
│    Leaking: UNKNOWN
│    ↓ FastSafeIterableMap.mHashMap
│                          ~~~~~~~~
├─ java.util.HashMap instance
│    Leaking: UNKNOWN
│    ↓ HashMap.table
│              ~~~~~
├─ java.util.HashMap$Node[] array
│    Leaking: UNKNOWN
│    ↓ HashMap$Node[].[8]
│                     ~~~
├─ java.util.HashMap$Node instance
│    Leaking: UNKNOWN
│    ↓ HashMap$Node.key
│                   ~~~
├─ androidx.viewpager2.adapter.FragmentStateAdapter$5 instance
│    Leaking: UNKNOWN
│    Anonymous class implementing androidx.lifecycle.LifecycleEventObserver
│    ↓ FragmentStateAdapter$5.this$0
│                             ~~~~~~
├─ com.surprise.common.presentation.view.adapter.PagerAdapter instance
│    Leaking: UNKNOWN
│    ↓ PagerAdapter.mFragments
│                   ~~~~~~~~~~
├─ androidx.collection.LongSparseArray instance
│    Leaking: UNKNOWN
│    ↓ LongSparseArray.mValues
│                      ~~~~~~~
├─ java.lang.Object[] array
│    Leaking: UNKNOWN
│    ↓ Object[].[0]
│               ~~~
╰→ com.surprise.feature.section.presentation.SectionFragment instance
​     Leaking: YES (ObjectWatcher was watching this because com.surprise.feature.section.presentation.SectionFragment received Fragment#onDestroy() callback and Fragment#mFragmentManager is null)
​     key = a4fbee3f-a0a2-464d-93ef-ae22a962a337
​     watchDurationMillis = 126195
​     retainedDurationMillis = 121174

METADATA

Build.VERSION.SDK_INT: 29
Build.MANUFACTURER: Google
LeakCanary version: 2.4
App process name: com.surprise.qual.pushdev.debug
Analysis duration: 622822 ms

Upvotes: 1

Views: 116

Answers (0)

Related Questions