2016-04-22 5 views
5

Ich höre Änderungen im Hinblick auf Layout ein OnGlobalLayoutListener mit:Kann ein nicht entfernter ViewTreeObserver-Listener Speicherlecks verursachen?

view.getViewTreeObserver().addOnGlobalLayoutListener(myListener); 

Da ich so lange in die Ereignisse dieses Zuhörer interessiert als die Aussicht besteht ich keine Notwendigkeit sehen removeOnGlobalLayoutListener(myListener) zu nennen.

Kann dies Speicherlecks verursachen oder wird der Listener Garbage zusammen mit der Ansicht gesammelt? Angenommen, der Listener enthält einen Verweis auf die Ansicht.

Der Hintergrund ist, dass ich ein Modul erstellen möchte, das an bestimmte Ansichten angehängt werden kann und auf Layoutänderungen basiert. Wenn das Entfernen nicht notwendig ist, wäre seine Erstellung genauso einfach wie new FancyModule(theView) und der Konstruktor kümmert sich dann um die Bindung des Hörers. Wenn das Entfernen notwendig ist, müsste ich eine Destruktor-Methode implementieren, die ich gerne verhindern möchte.

Antwort

3

Ein potenzielles Speicherleck hängt nur von Ihrer Architektur ab.

Normalerweise ist es in Ordnung, nicht removeOnGlobalLayoutListener(myListener) zu rufen. View enthält Verweis auf ViewTreeObserver, die Verweis auf OnGlobalLayoutListener enthält. Wenn Sie keinen weiteren Verweis auf den Listener haben, wird entlang der Ansicht Müll gesammelt.

Nun, wenn Ihre Implementierung von OnGlobalLayoutListener Verweis auf die Ansicht hält, ist es immer noch in Ordnung. Ein Referenzzyklus ist kein Problem für Android Garbage Collector.

Ein Problem kann erstellt werden, wenn Sie eine andere Komponente haben, die auf die Implementierung OnGlobalLayoutListener verweist. Wenn die Komponente länger als die Ansicht lebt (z. B. wenn sie über das Anwendungsobjekt gehalten wird), erstellen Sie ein Speicherleck der Ansicht (und des Kontexts) durch den Listener.

Es ist wichtig, die Ansicht nicht zu halten, wenn sie nicht mehr verwendet wird. Eine einfache Möglichkeit, die Sicht zu vermeiden, besteht darin, WeakReference zu verwenden.

+0

Der Listener und die Ansicht enthalten nur eine zyklische Referenz zueinander. Keine andere Komponente ist beteiligt. Ich war mir nicht sicher, ob ein 'getViewTreeObserver() 'einer Ansicht möglicherweise Objekte zurückgeben könnte, die länger als die Ansicht selbst leben. – McFarlane

+0

Nun, wenn nichts anderes den Referenzzyklus von außen hält, ist es in Ordnung. – Tomik

0

Ja, es kann undicht werden. Hier ist ein Beispiel Spur von LeakCanary,

  • com.xxx.Activity hat durchgesickert:
  • GC ROOT statische android.view.inputmethod.InputMethodManager.sInstance
  • Referenzen android.view.inputmethod.InputMethodManager.mCurRootView
  • Referenzen com.android.internal.policy.DecorView.mAttachInfo
  • Referenzen android.view.View $ AttachInfo.mTreeObserver
  • Referenzen android.view.ViewTreeObserver.mOnGlobalLayoutListeners
  • Referenzen android.view.ViewTreeObserver $ CopyOnWriteArray.mData
  • Referenzen java.util.ArrayList.elementData
  • Referenzen Array java.lang.Object []. [0]
  • Referenzen com.xxx.Activity $ setExpandedToolbarHeight $ layoutListener $ 1.this $ 0 (anonym Implementierung von android.view.ViewTreeObserver $ OnGlobalLayoutListener)
  • Lecks com.xxx.Aktivitätsinstanz
+0

Können Sie Ihre Antwort mit Code-Snippets erweitern, die zeigen, wie Sie den Listener verwendet haben? – McFarlane

Verwandte Themen