为什么 AccessibilityManager.sInstance 会导致内存泄漏?

And*_*ner 3 java android android-activity leakcanary

我有一个包含片段的活动。运行 Leak Canary,我发现该活动存在内存泄漏。

我已经注释掉了活动和片段中的所有代码,其中活动仅显示片段并且片段具有空的 xml 布局。我在文件或 xml 中都没有可访问性。

* AccessibilityManager$1.!(this$0)! (anonymous subclass of android.view.accessibility.IAccessibilityManagerClient$Stub)
* ? AccessibilityManager.!(mTouchExplorationStateChangeListeners)!
* ? CopyOnWriteArrayList.!(elements)!
* ? array Object[].!([2])!
* ? AccessibilityManagerCompat$TouchExplorationStateChangeListenerWrapper.!(mListener)!
* ? BaseTransientBottomBar$SnackbarBaseLayout$1.!(this$0)! (anonymous implementation of android.support.v4.view.accessibility.AccessibilityManagerCompat$TouchExplorationStateChangeListener)
* ? Snackbar$SnackbarLayout.mContext
* ? ContextThemeWrapper.mBase
* ? MessagesActivity
Run Code Online (Sandbox Code Playgroud)

Xi *_*Wei 5

好吧,我真的弄明白了。这是 Snackbar 中的内存泄漏,这里是如何重现它:https : //github.com/GC-Xi/SnackbarBug

繁殖方式

  1. 创建一个 Snackbar 并在 Activity 中引用它
  2. 不要调用 Snackbar.show()
  3. 打开和关闭活动
  4. 请注意,该 Activity 不会被垃圾收集,因为小吃店有对它的引用

原因

构造函数中的SnackbarBaseLayout调用addTouchExplorationStateChangeListener()和. 可能应该从哪里调用 ,因为除非被调用,否则它不附加到窗口。removeTouchExplorationStateChangeListener()onDetachedFromWindow()addTouchExplorationStateChangeListener()onAttachedToWindow()SnackbarBaseLayoutSnackbar.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