2016-04-22 67 views
5

私はOnGlobalLayoutListenerを使用してビューの変更をレイアウトするのに聞いている:ViewTreeObserverリスナーを削除できないとメモリリークが発生する可能性がありますか?

view.getViewTreeObserver().addOnGlobalLayoutListener(myListener); 

私がいる限りビューは、私がremoveOnGlobalLayoutListener(myListener)を呼び出す必要を見ない存在として、このリスナーのイベントに興味がありますので。

これはメモリリークを引き起こす可能性がありますか、またはリスナーガベージがビューと共に収集される可能性がありますか?リスナーがビューへの参照を保持しているとします。


backgoundは、特定のビューにアタッチできるモジュールを作成し、レイアウトの変更に基づいて処理するモジュールです。取り除く必要がない場合、作成はnew FancyModule(theView)と同じくらい単純なので、コンストラクターはリスナーのバインドを処理します。削除が必要な場合は、私が避けたいデストラクタメソッドを実装する必要があります。

答えて

3

潜在的なメモリリークは、ご使用のアーキテクチャによってのみ異なります。

通常、removeOnGlobalLayoutListener(myListener)に電話しないでください。 Viewは、ViewTreeObserverへの参照を保持しており、これには、OnGlobalLayoutListenerという参照が追加されています。リスナーへの別の参照がない場合は、ビューに沿ってガベージコレクションされます。

OnGlobalLayoutListenerの実装では、ビューへの参照が保持されていれば、それでも問題ありません。リファレンスサイクルはAndroidのガベージコレクタにとって問題ではありません。

OnGlobalLayoutListener実装への参照を保持する別のコンポーネントがある場合は、問題が発生する可能性があります。コンポーネントがビューよりも長く存在する場合(アプリケーションオブジェクトを介して保持されるなど)、リスナーを介してビュー(およびコンテキスト)のメモリリークが作成されます。

ビューが使用されなくなったら保持しないことが重要です。ビューを漏らさないようにする簡単な方法は、WeakReferenceを使用することです。

+0

リスナーとビューは、相互に循環参照のみを保持します。他のコンポーネントは関与していません。ビューの 'getViewTreeObserver()'がビュー自体よりも長く生きているオブジェクトを返す可能性があるかどうかはわかりませんでした。 – McFarlane

+0

それ以外のものが外部から基準サイクルを保持していなければ、それは問題ありません。 – Tomik

0

はい、漏れる可能性があります。

  • 参照が
  • をandroid.view.inputmethod.InputMethodManager.mCurRootView
  • GCのROOT静的android.view.inputmethod.InputMethodManager.sInstance:ここLeakCanaryから例のトレース、

    • com.xxx.Activityが漏れたのです
    • 参照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

    関連する問題