2016-04-22 4 views
5

sto ascoltando il layout cambiamenti di una vista utilizzando un OnGlobalLayoutListener:Un listener ViewTreeObserver non rimosso può causare perdite di memoria?

view.getViewTreeObserver().addOnGlobalLayoutListener(myListener); 

Dal momento che sono interessato alle vicende di questo ascoltatore fino a quando la vista esiste non vedo la necessità di chiamare removeOnGlobalLayoutListener(myListener).

Ciò può causare perdite di memoria o la garbage listener viene raccolta insieme alla vista? Supponiamo che l'ascoltatore abbia un riferimento alla vista.


Il backgound è che voglio creare un modulo che può essere collegato a determinati punti di vista e fa cose in base alle modifiche del layout. Se la rimozione non è necessaria, la sua creazione sarebbe semplice come new FancyModule(theView) e il costruttore si occuperà quindi di legare l'ascoltatore. Se la rimozione è necessaria, dovrei implementare un metodo distruttore che vorrei impedire.

risposta

3

La perdita di memoria potenziale dipende solo dall'architettura.

Normalmente, non è necessario chiamare removeOnGlobalLayoutListener(myListener). View detiene il riferimento a ViewTreeObserver che contiene il riferimento a OnGlobalLayoutListener aggiunto. Se non si dispone di un altro riferimento per l'ascoltatore, è garbage collection lungo la vista.

Ora, se l'implementazione di OnGlobalLayoutListener contiene riferimento alla vista, è ancora valida. Un ciclo di riferimento non è un problema per il garbage collector di Android.

Un problema può essere creato se si dispone di un altro componente che contiene riferimento all'implementazione OnGlobalLayoutListener. Se il componente vive più a lungo della vista (ad es. Viene tenuto tramite l'oggetto applicazione), si crea una perdita di memoria della vista (e del contesto) attraverso l'ascoltatore.

È importante non mantenere la vista quando non è più utilizzata. Un modo semplice per evitare perdite di vista è utilizzare WeakReference.

+0

L'ascoltatore e la vista mantengono solo un riferimento ciclico l'uno con l'altro. Nessun altro componente è coinvolto. Non ero sicuro che una vista 'getViewTreeObserver()' potesse restituire oggetti che vivono più a lungo della vista stessa. – McFarlane

+0

Bene, se nient'altro mantiene il ciclo di riferimento dall'esterno, allora va bene. – Tomik

0

Sì, può fuoriuscire. Ecco un esempio dalla traccia LeakCanary,

  • com.xxx.Activity è trapelato:
  • GC ROOT android.view.inputmethod.InputMethodManager.sInstance statico
  • riferimenti android.view.inputmethod.InputMethodManager.mCurRootView
  • riferimenti com.android.internal.policy.DecorView.mAttachInfo
  • riferimenti android.view.View $ AttachInfo.mTreeObserver
  • riferimenti android.view.ViewTreeObserver.mOnGlobalLayoutListeners
  • riferimenti android.view.ViewTreeObserver $ CopyOnWriteArray.mData
  • riferimenti java.util.ArrayList.elementData
  • riferimenti ad array java.lang.Object []. [0]
  • riferimenti com.xxx.Activity $ setExpandedToolbarHeight $ layoutListener $ 1.This $ 0 (implementazione anonima di android.view.ViewTreeObserver $ OnGlobalLayoutListener)
  • perdite com.xxx.Istanza attività
+0

Puoi estendere la risposta con frammenti di codice che mostrano come hai usato l'ascoltatore? – McFarlane