我有一个包含 fragment 的 Activity 。运行 Leak Canary,我发现该 Activity 存在内存泄漏。
我已经注释掉了从 Activity 和 fragment 到 Activity 仅显示 fragment 并且 fragment 具有空 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
最佳答案
好吧,我真的明白了。这是 Snackbar 中的内存泄漏,这里是如何重现它的:https://github.com/GC-Xi/SnackbarBug
重现方式
- 创建一个 Snackbar 并在 Activity 中引用它
- 不要调用 Snackbar.show()
- 打开和关闭 Activity
- 请注意该 Activity 未被垃圾回收,因为 snackbar 引用了它
原因
SnackbarBaseLayout
在构造函数中调用 addTouchExplorationStateChangeListener()
并在 onDetachedFromWindow()
中调用 removeTouchExplorationStateChangeListener()
。 addTouchExplorationStateChangeListener()
可能应该从 onAttachedToWindow()
调用,因为 SnackbarBaseLayout
没有附加到窗口,除非 Snackbar.show( )
被调用。
解决方案一
更新到 AndroidX 并改用 com.google.android.material.snackbar.Snackbar。 https://github.com/GC-Xi/SnackbarBug/tree/solution1
方案二
除非您准备好展示它,否则不要创建 Snackbar。 https://github.com/GC-Xi/SnackbarBug/tree/solution2
关于java - 为什么 AccessibilityManager.sInstance 会导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55697904/