2016-04-22 36 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

相關問題