Navigation Arch Componentは誤検知のメモリリークを引き起こす可能性がありますか?


14

メモリリークとその原因についての基本的な知識があります。そのため、コードに問題があるのか​​、それとも誤検知なのかわかりません。プロジェクトは小さくないので、コードのどの部分を共有するべきかわかりません。ただし、コメント欄でお知らせください。必要なコードを追加します。

ナビゲーションアーチコンポーネントを使用し、MVVMパターンに従います。プロジェクトの開発の後半でLeakCanaryライブラリを追加したところ、画面間を移動すると、保持されたインスタンスに関する警告がすぐに表示され始めました。

この問題は、バックスタックにフラグメントを追加すると発生します。バックスタックにフラグメントを追加するたびに、保持されるインスタンスのカウンターが増加します。LeakCanaryがしきい値の5に達すると、ヒープがダンプされ、レポートが提供されます。

しかし、[戻る]ボタンをクリックして前の画面に戻ると、保持されているインスタンスのカウンターが減少し、最終的に1番目の画面に戻ると、保持されているすべてのインスタンスが消えます。

ヒープ分析レポートを見るとCoordinatorLayout、XML内の参照である変数coordinatorLayout がリークしていることがわかります。変数とそのすべての使用法を削除してアプリを再度実行すると、同じ問題が発生しますが、別の変数がxml内の別のビューへの参照になっています。LeakCanaryがリークしていると報告したすべてのビューとその使用法を削除しようとしました。TextViewテキストを設定するためだけに使用され、onViewCreated他の場所では使用されていないがリークしていると言われたとき、コードに問題があることに疑問を感じ始めました。

ライフサイクルメソッドの呼び出しをフラグメントで分析しましたが、前のフラグメントの新しい画面に移動するonDestroyViewと、呼び出されるまでのすべてのメソッドが呼び出されますが、呼び出されませんでしたonDestroy。[戻る]をクリックするとonDestroy、バックスタックの上にあるフラグメントが呼び出され、保持されているインスタンスのカウンターが減少します。

ナビゲーションコンポーネントがフラグメントがバックスタックにあるときにフラグメントのインスタンスを保持しており、LeakCanaryがそれをリークとして認識していると思います。

回答:


24

これが、バックスタックのフラグメントが機能する方法です(ナビゲーションは既存のフラグメントAPIを使用するだけです)。フラグメントのビューは破棄されますが、フラグメント自体は破棄されません。これらはCREATED、[戻る]ボタンをクリックしてフラグメントに戻るまでその状態に保たれます。 (その後onCreateView()再び呼び出され、上に戻りますRESUMED)。

あたりとしてフラグメント:過去、現在、そして未来の話、将来のいずれかがフラグメントに来る変わりはなく、二つの別々のライフサイクルを持つよりも、バックスタック上のフラグメントを破壊するためのオプションでoptです。これはまだ利用できません。

でビューへの参照を無効にする必要があります。onDestroyViewこれは、ビューがフラグメントシステムで使用されなくなったことを示しており、ビューへの継続的な参照がなければ、ガベージコレクションを安全に実行できます。


2
Android View Bindingはこの問題を解決しますか?ビューバインディングビュー(おそらくバインディングオブジェクト自体)への参照がビューバインディングで自動的に「nullアウト」されるかどうかに関するドキュメントは見つかりませんonDestroyView
Tim Malseed

3
@TimMalseed-バインディングオブジェクトへの参照を自分でnullにする必要があります。自動的に行われることはありません。
ianhanniballake

1
@Emmanuel-所有するビューへのハード参照を保持しているため、バインディングオブジェクト自体への参照を削除する必要があります。
ianhanniballake

1
@Emmanuel- 機能リクエストはいつでも提出できます
ianhanniballake

1
@Emmanuel-これは確かに動作の変更(別のオプトインフラグであることを意味する可能性があります)になると思いますが、正しいLifecycleOwnerがあれば、メモリの問題全体を修正するのに十分な情報になります。
ianhanniballake
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.