2016-04-22 824 views
5

我听使用OnGlobalLayoutListener布局视图的变化:不能删除的ViewTreeObserver侦听器是否会导致内存泄漏?

view.getViewTreeObserver().addOnGlobalLayoutListener(myListener); 

因为我很感兴趣,只要视图是否存在我认为没有必要调用removeOnGlobalLayoutListener(myListener)这个监听的事件。

这可能导致内存泄漏,或者是与视图一起收集的侦听器垃圾?假设监听者拥有对视图的引用。


背景是,我想创建一个模块,可以附加到某些视图,并根据布局更改做东西。如果不需要删除,那么它的创建就像new FancyModule(theView)一样简单,然后构造函数负责绑定侦听器。如果需要移除,我必须实现一个我想要阻止的析构函数方法。

回答

3

潜在的内存泄漏仅取决于您的体系结构。

通常,不要致电removeOnGlobalLayoutListener(myListener)View持有参考ViewTreeObserver其中持有参考添加OnGlobalLayoutListener。如果您没有对侦听器的其他引用,则会沿着视图收集垃圾。

现在,如果您的实施OnGlobalLayoutListener持有对视图的引用,它仍然很好。 Android的垃圾收集器的引用周期不是问题。

如果您拥有对OnGlobalLayoutListener实施的引用的其他组件,则可能会产生问题。如果组件的生命周期比视图长(例如,它通过应用程序对象持有),则通过侦听器创建视图(和上下文)的内存泄漏。

当不再使用视图时,非常重要。如何避免泄漏视图的简单方法是使用WeakReference

+0

侦听器和视图只保存彼此的循环引用。没有涉及其他组件。我不确定一个视图的getViewTreeObserver()是否可能返回比视图本身更长的对象。 – McFarlane

+0

好吧,如果没有别的东西从外面持有参考周期,那就没问题。 – Tomik

0

是的,它可以泄漏。下面是LeakCanary一个例子痕迹,

  • com.xxx.Activity渗漏:
  • GC ROOT静态android.view.inputmethod.InputMethodManager.sInstance
  • 引用android.view.inputmethod.InputMethodManager.mCurRootView
  • 引用com.android.internal.policy.DecorView.mAttachInfo
  • 引用android.view.View $ AttachInfo.mTreeObserver
  • 引用android.view.ViewTreeObserver.mOnGlobalLayoutListeners
  • 引用android.view.ViewTreeObserver $ CopyOnWriteArray.mData
  • 引用java.util.ArrayList.elementData
  • 引用数组java.lang.Object中[]。[0]
  • 引用com.xxx.Activity $ setExpandedToolbarHeight $ layoutListener $ 1,本$ 0(匿名执行android.view.ViewTreeObserver $ OnGlobalLayoutListener的)
  • 泄漏com.xxx。活动实例
+0

您可以使用代码片段来展示您如何使用侦听器的答案吗? – McFarlane

相关问题