litrik / MotionLayoutLeak

Sample app demonstrating a memory leak in MotionLayout

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MotionLayout keeps track of any nested scrollable view in its mScrollTarget field. This causes a memory leak when that view has a different lifecycle than the MotionLayout. For example: a NestedScrollView is inside a Fragment that gets removed from the MotionLayout.

This happens with MotionLayout 2.0.0-beta5, 2.0.0-beta6 and 2.0.0-beta7. It did not happen in 2.0.0-beta4.

To reproduce:

  • Start the app
  • Click on the button to go to the second fragment
  • Scroll through the images
  • Press back to close the second fragment
  • Press Home

Leak Canary detects the following leak:

hprof: heap dump "/data/user/0/be.norio.sandbox.motionlayoutleak/files/leakcanary/2020-06-15_10-21-02_146.hprof" starting...
hprof: heap dump completed (15MB) in 632.111ms objects 238748 objects with stack traces 0
Analysis in progress, working on: PARSING_HEAP_DUMP
Analysis in progress, working on: EXTRACTING_METADATA
Analysis in progress, working on: FINDING_RETAINED_OBJECTS
Analysis in progress, working on: FINDING_PATHS_TO_RETAINED_OBJECTS
Analysis in progress, working on: FINDING_DOMINATORS
Found 2 retained objects
Analysis in progress, working on: COMPUTING_NATIVE_RETAINED_SIZE
Analysis in progress, working on: COMPUTING_RETAINED_SIZE
Analysis in progress, working on: BUILDING_LEAK_TRACES
Found 2 paths to retained objects, down to 1 after removing duplicated paths
Analysis in progress, working on: REPORTING_HEAP_ANALYSIS
====================================
HEAP ANALYSIS RESULT
====================================
1 APPLICATION LEAKS
References underlined with "~~~" are likely causes.
Learn more at https://squ.re/leaks.
2478 bytes retained by leaking objects
Signature: 1ac98bd3de32512986d7573ad8bd69aaaf51c7c8
┬───
│ 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.mNextServedView
├─ com.android.internal.policy.DecorView instance
│    Leaking: NO (LinearLayout↓ is not leaking and View attached)
│    mContext instance of com.android.internal.policy.DecorContext, wrapping activity be.norio.sandbox.motionlayoutleak.MainActivity with mDestroyed = false
│    Parent android.view.ViewRootImpl not a android.view.View
│    View#mParent is set
│    View#mAttachInfo is not null (view attached)
│    View.mWindowAttachCount = 1
│    ↓ DecorView.mContentRoot
├─ android.widget.LinearLayout instance
│    Leaking: NO (MainActivity↓ is not leaking and View attached)
│    mContext instance of be.norio.sandbox.motionlayoutleak.MainActivity with mDestroyed = false
│    View.parent com.android.internal.policy.DecorView attached as well
│    View#mParent is set
│    View#mAttachInfo is not null (view attached)
│    View.mWindowAttachCount = 1
│    ↓ LinearLayout.mContext
├─ be.norio.sandbox.motionlayoutleak.MainActivity instance
│    Leaking: NO (ContentFrameLayout↓ is not leaking and Activity#mDestroyed is false)
│    ↓ MainActivity.mDelegate
├─ androidx.appcompat.app.AppCompatDelegateImpl instance
│    Leaking: NO (ContentFrameLayout↓ is not leaking)
│    ↓ AppCompatDelegateImpl.mActionBar
├─ androidx.appcompat.app.WindowDecorActionBar instance
│    Leaking: NO (ContentFrameLayout↓ is not leaking)
│    ↓ WindowDecorActionBar.mContentView
├─ androidx.appcompat.widget.ContentFrameLayout instance
│    Leaking: NO (MotionLayout↓ is not leaking and View attached)
│    mContext instance of androidx.appcompat.view.ContextThemeWrapper, wrapping activity be.norio.sandbox.motionlayoutleak.MainActivity with mDestroyed = false
│    View.parent androidx.appcompat.widget.ActionBarOverlayLayout attached as well
│    View#mParent is set
│    View#mAttachInfo is not null (view attached)
│    View.mID = R.id.null
│    View.mWindowAttachCount = 1
│    ↓ ContentFrameLayout.mChildren
├─ android.view.View[] array
│    Leaking: NO (MotionLayout↓ is not leaking)
│    ↓ View[].[0]
├─ androidx.constraintlayout.motion.widget.MotionLayout instance
│    Leaking: NO (View attached)
│    mContext instance of be.norio.sandbox.motionlayoutleak.MainActivity with mDestroyed = false
│    View.parent androidx.appcompat.widget.ContentFrameLayout attached as well
│    View#mParent is set
│    View#mAttachInfo is not null (view attached)
│    View.mWindowAttachCount = 1
│    ↓ MotionLayout.mScrollTarget
│                   ~~~~~~~~~~~~~
├─ androidx.core.widget.NestedScrollView instance
│    Leaking: YES (View detached and has parent)
│    mContext instance of be.norio.sandbox.motionlayoutleak.MainActivity with mDestroyed = false
│    View#mParent is set
│    View#mAttachInfo is null (view detached)
│    View.mWindowAttachCount = 1
│    ↓ NestedScrollView.mParent
╰→ android.widget.FrameLayout instance
​     Leaking: YES (ObjectWatcher was watching this because be.norio.sandbox.motionlayoutleak.FragmentTwo received Fragment#onDestroyView() callback (references to its views should be cleared to prevent leaks))
​     key = c6cfcd15-f899-46ea-8079-220c8f3ad68f
​     watchDurationMillis = 8219
​     retainedDurationMillis = 3181
​     mContext instance of be.norio.sandbox.motionlayoutleak.MainActivity with mDestroyed = false
​     View#mParent is null
​     View#mAttachInfo is null (view detached)
​     View.mWindowAttachCount = 1
====================================
0 LIBRARY LEAKS
A Library Leak is a leak caused by a known bug in 3rd party code that you do not have control over.
See https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/#4-categorizing-leaks
====================================
METADATA
Please include this in bug reports and Stack Overflow questions.
Build.VERSION.SDK_INT: 29
Build.MANUFACTURER: Google
LeakCanary version: 2.3
App process name: be.norio.sandbox.motionlayoutleak
Analysis duration: 5423 ms
Heap dump file path: /data/user/0/be.norio.sandbox.motionlayoutleak/files/leakcanary/2020-06-15_10-21-02_146.hprof
Heap dump timestamp: 1592209268241
====================================

About

Sample app demonstrating a memory leak in MotionLayout


Languages

Language:Kotlin 100.0%