Как я могу увидеть утечку?

#android #memory-leaks #leakcanary

Вопрос:

Я пытаюсь устранить эти утечки. Но я понятия не имею, в чем проблема.

1.

 ┬───
│ GC Root: System class
│
├─ android.os.Looper class
│    Leaking: NO (Thread↓ is not leaking and a class is never leaking)
│    ↓ static Looper.sMainLooper
├─ android.os.Looper instance
│    Leaking: NO (Thread↓ is not leaking)
│    ↓ Looper.mThread
├─ java.lang.Thread instance
│    Leaking: NO (the main thread always runs)
│    Thread name: 'main'
│    ↓ Thread.threadLocals
│             ~~~~~~~~~~~~
├─ java.lang.ThreadLocal$ThreadLocalMap instance
│    Leaking: UNKNOWN
│    Retaining 2.2 kB in 69 objects
│    ↓ ThreadLocal$ThreadLocalMap.table
│                                 ~~~~~
├─ java.lang.ThreadLocal$ThreadLocalMap$Entry[] array
│    Leaking: UNKNOWN
│    Retaining 2.1 kB in 68 objects
│    ↓ ThreadLocal$ThreadLocalMap$Entry[].[21]
│                                         ~~~~
├─ java.lang.ThreadLocal$ThreadLocalMap$Entry instance
│    Leaking: UNKNOWN
│    Retaining 28 B in 1 objects
│    ↓ ThreadLocal$ThreadLocalMap$Entry.value
│                                       ~~~~~
├─ android.animation.AnimationHandler instance
│    Leaking: UNKNOWN
│    Retaining 29.7 MB in 54029 objects
│    ↓ AnimationHandler.mAnimationCallbacks
│                       ~~~~~~~~~~~~~~~~~~~
├─ java.util.ArrayList instance
│    Leaking: UNKNOWN
│    Retaining 29.7 MB in 54025 objects
│    ↓ ArrayList.elementData
│                ~~~~~~~~~~~
├─ java.lang.Object[] array
│    Leaking: UNKNOWN
│    Retaining 29.7 MB in 54024 objects
│    ↓ Object[].[0]
│               ~~~
├─ android.animation.ValueAnimator instance
│    Leaking: UNKNOWN
│    Retaining 875 B in 28 objects
│    ↓ Animator.mListeners
│               ~~~~~~~~~~
├─ java.util.ArrayList instance
│    Leaking: UNKNOWN
│    Retaining 60 B in 2 objects
│    ↓ ArrayList.elementData
│                ~~~~~~~~~~~
├─ java.lang.Object[] array
│    Leaking: UNKNOWN
│    Retaining 40 B in 1 objects
│    ↓ Object[].[0]
│               ~~~
├─ android.view.ViewPropertyAnimator$AnimatorEventListener instance
│    Leaking: UNKNOWN
│    Retaining 368 B in 12 objects
│    ↓ ViewPropertyAnimator$AnimatorEventListener.this$0
│                                                 ~~~~~~
├─ android.view.ViewPropertyAnimator instance
│    Leaking: UNKNOWN
│    Retaining 356 B in 11 objects
│    ↓ ViewPropertyAnimator.mView
│                           ~~~~~
├─ androidx.appcompat.widget.AppCompatImageView instance
│    Leaking: YES (View.mContext references a destroyed activity)
│    Retaining 1.2 kB in 19 objects
│    View is part of a window view hierarchy
│    View.mAttachInfo is null (view detached)
│    View.mID = R.id.iv_energy
│    View.mWindowAttachCount = 1
│    mContext instance of com.example.components.ui.result.
│    ResultVer2Activity with mDestroyed = true
│    ↓ View.mContext
╰→ com.example.components.ui.result.ResultVer2Activity instance
​     Leaking: YES (ObjectWatcher was watching this because com.example.components.ui.result.ResultVer2Activity received
​     Activity#onDestroy() callback and Activity#mDestroyed is true)
​     Retaining 18.4 MB in 13058 objects
​     key = dc4c55d5-5d97-4091-b7ad-0cd2a49f4d09
​     watchDurationMillis = 6804
​     retainedDurationMillis = 1799
​     mApplication instance of com.example.MyApplication
​     mBase instance of androidx.appcompat.view.ContextThemeWrapper

METADATA

Build.VERSION.SDK_INT: 30
Build.MANUFACTURER: Google
LeakCanary version: 2.6
App process name: com.example
Count of retained yet cleared: 12 KeyedWeakReference instances
Stats: LruCache[maxSize=3000,hits=8027,misses=155358,hitRate=4%]
RandomAccess[bytes=7640055,reads=155358,travel=107845991097,range=28570681,size=
41968225]
Heap dump reason: 7 retained objects, app is visible
Analysis duration: 87264 ms
 
 │ GC Root: Global variable in native code
│
├─ android.widget.Toast$TN instance
│    Leaking: UNKNOWN
│    Retaining 524.3 kB in 16111 objects
│    ↓ Toast$TN.mPresenter
│               ~~~~~~~~~~
├─ android.widget.ToastPresenter instance
│    Leaking: UNKNOWN
│    Retaining 522.4 kB in 16104 objects
│    mContext instance of com.example.components.ui.exam.
│    ExamEntryActivity with mDestroyed = true
│    ↓ ToastPresenter.mContext
│                     ~~~~~~~~
╰→ com.example.components.ui.exam.ExamEntryActivity instance
     Leaking: YES (ObjectWatcher was watching this because com.example.components.ui.exam.ExamEntryActivity received
     Activity#onDestroy() callback and Activity#mDestroyed is true)
     Retaining 354.3 kB in 12305 objects
     key = dce008b9-d99a-4dfa-be4f-a5b0ae8917cb
     watchDurationMillis = 57521
     retainedDurationMillis = 52002
     mApplication instance of com.example.MyApplication
     mBase instance of androidx.appcompat.view.ContextThemeWrapper

METADATA

Build.VERSION.SDK_INT: 30
Build.MANUFACTURER: Google
LeakCanary version: 2.6
App process name: com.example
Count of retained yet cleared: 2 KeyedWeakReference instances
Stats: LruCache[maxSize=3000,hits=10382,misses=177073,hitRate=5%]
RandomAccess[bytes=10509449,reads=177073,travel=81077330786,range=32700295,size=
48659081]
Heap dump reason: 6 retained objects, app is visible
Analysis duration: 16424 ms
 

Как я могу прочитать эту трассировку и устранить проблему?

Ответ №1:

Первая утечка происходит из-за того, что что-то настраивает аниматор на R. id.iv_energy ImageView. Аниматор должен быть отменен, когда этот вид отсоединен, но это не так, аниматор все еще работает и удерживает изображение.

Второе происходит потому, что тост произносит местный судья. Отмена тоста может помочь или создать тост с контекстом приложения вместо контекста действия.