Есть ли причина, по которой AccessibilityManager.sInstance может вызвать утечку памяти? - PullRequest
3 голосов
/ 16 апреля 2019

У меня есть активность, которая содержит фрагмент. Запустив Leak Canary, я вижу, что у активности есть утечка памяти. Я закомментировал весь код из действия и фрагмента, где активность показывает только фрагмент, а фрагмент имеет пустую разметку XML. У меня нет доступа ни к файлу, ни к XML.

  • AccessibilityManager $ 1.! (Это $ 0)! (анонимный подкласс android.view.accessibility.IAccessibilityManagerClient $ Stub)
  • ↳ AccessibilityManager.! (MTouchExplorationStateChangeListeners)!
  • ↳ CopyOnWriteArrayList.! (Elements)!
  • ↳ Объект массива [].! ([2])!
  • ↳ AccessibilityManagerCompat $ TouchExplorationStateChangeListenerWrapper.! (MListener)!
  • ↳ BaseTransientBottomBar $ SnackbarBaseLayout $ 1.! (Это $ 0)! (анонимная реализация android.support.v4.view.accessibility.AccessibilityManagerCompat $ TouchExplorationStateChangeListener)
  • ↳ Снэк-бар $ SnackbarLayout.mContext
  • ↳ ContextThemeWrapper.mBase
  • ↳ СообщенияДеятельность

Ответы [ 2 ]

4 голосов
/ 14 мая 2019

ОК, я на самом деле понял это.Это утечка памяти в Snackbar, и вот как ее можно воспроизвести: https://github.com/GC-Xi/SnackbarBug

Способ воспроизведения

  1. Создание Snackbar и ссылка на него вактивность
  2. Не вызывайте Snackbar.show ()
  3. Откройте и закройте операцию
  4. Обратите внимание, что операция не является сборщиком мусора, потому что на снэк-бар есть ссылка

Причина

SnackbarBaseLayout вызывает addTouchExplorationStateChangeListener() в конструкторе и removeTouchExplorationStateChangeListener() в onDetachedFromWindow().Где addTouchExplorationStateChangeListener(), вероятно, следует вызывать из onAttachedToWindow(), поскольку SnackbarBaseLayout не привязан к окну, если не вызывается Snackbar.show().

Решение 1

Обновите AndroidX и используйте вместо него com.google.android.material.snackbar.Snackbar.https://github.com/GC-Xi/SnackbarBug/tree/solution1

Решение 2

Не создавайте Snackbar, если вы не готовы его показать.https://github.com/GC-Xi/SnackbarBug/tree/solution2

1 голос
/ 09 мая 2019

Я столкнулся с подобной проблемой.Я держал ссылку на Закусочную.После удаления этой ссылки утечка памяти исчезла.

Обновление

Например, замените

val snackbar = Snackbar.make(rootLayout, "Hello Snackbar", Snackbar.LENGTH_INDEFINITE)
snackbar.show()

на

Snackbar.make(rootLayout, "Hello Snackbar", Snackbar.LENGTH_INDEFINITE).show()

Я не знаю, почему это решило мою проблему.Я не смог воспроизвести эту утечку памяти в других проектах.На основании трассировки стека кажется, что BaseTransientBottomBar.onDetachedFromWindow() не вызывается системой, поэтому touchExplorationStateChangeListener не удаляется из accessibilityManager.Опять же, я не знаю, почему это произошло.Ниже приведен код для BaseTransientBottomBar.onDetachedFromWindow().

    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (this.onAttachStateChangeListener != null) {
            this.onAttachStateChangeListener.onViewDetachedFromWindow(this);
        }

        AccessibilityManagerCompat.removeTouchExplorationStateChangeListener(this.accessibilityManager, this.touchExplorationStateChangeListener);
    } 
...