フラグメントのsetRetainInstance(boolean)を理解する


341

ドキュメントから始める:

public void setRetainInstance(ブール保持)

アクティビティの再作成(構成の変更など)を通じてフラグメントインスタンスを保持するかどうかを制御します。これは、バックスタックにないフラグメントでのみ使用できます。設定されている場合、アクティビティが再作成されるときのフラグメントのライフサイクルは少し異なります。

  • onDestroy()は呼び出されません(ただし、フラグメントが現在のアクティビティから切り離されているため、onDetach()は呼び出されます)。
  • フラグメントが再作成されていないため、onCreate(Bundle)は呼び出されません。
  • onAttach(Activity)とonActivityCreated(Bundle)は引き続き呼び出されます。

いくつか質問があります。

  • フラグメントはそのビューも保持しますか、それとも構成の変更時に再作成されますか?「保持」とはどういう意味ですか?

  • ユーザーがアクティビティを離れると、フラグメントは破棄されますか?

  • バックスタックのフラグメントで動作しないのはなぜですか?

  • この方法を使用することが理にかなっている使用例はどれですか?


回答:


348

まず、保持されているフラグメントに関する私の投稿をチェックしください。役立つかもしれません。

今あなたの質問に答えるために:

フラグメントはビューステートも保持しますか、それとも構成変更時に再作成されますか-正確に何が「保持」されますか?

はい、Fragment設定の変更後もの状態は保持されます。具体的には、「保持」とは、構成の変更時にフラグメントが破棄されないことを意味します。つまり、Fragmentされる保持構成変更が根本的な原因場合でもActivity破壊されます。

ユーザーがアクティビティを離れると、フラグメントは破棄されますか?

Activitys と同様に、Fragmentsはメモリリソースが不足するとシステムによって破棄される可能性があります。構成の変更後もフラグメントにインスタンスの状態を保持させるかどうかは、Fragmentいったんを離れると、システムがを破棄するかどうかには影響しませんActivityActivity(ホームボタンを押して)を離れると、Fragmentsが破壊される場合とされない場合があります。あなたがままにした場合Activity(したがって、呼び出し元のバックボタンを押すことでfinish()、効果的に破壊するActivity)、すべてのActivity添付sはFragmentSも破棄されます。

バックスタックのフラグメントで動作しないのはなぜですか?

そこには、サポートされていないいくつかの理由は、おそらくですが、私には最も明白な理由があるということActivityへの参照を保持しFragmentManager、かつFragmentManagerbackstackを管理します。つまり、Fragments を保持するかどうかに関係なく、Activity(およびFragmentManagerのバックスタック)は構成の変更時に破棄されます。機能しない可能性があるもう1つの理由は、保持されているフラグメント保持されていないフラグメントの両方が同じバックスタックに存在することが許可されていると、事態が複雑になる可能性があるためです。

この方法を使用することが理にかなっている使用例はどれですか?

保持されたフラグメントは、アクティビティインスタンス間で状態情報(特にスレッド管理)を伝播するのに非常に役立ちます。たとえば、フラグメントは、Threadまたはのインスタンスのホストとして機能し、AsyncTaskその操作を管理できます。詳細についてはこのトピックに関する私のブログ投稿を参照しください。

一般に、方向の変更を実装/処理するのが面倒だからといってonConfigurationChangedActivity... と一緒に使用するのと同じように扱います。必要なときにだけ使用してください。


37
ビューオブジェクトは保持されず、構成の変更時に常に破棄されます。
Markus Junginger

103
私の知る限りsetRetainInstance(true)では、FragmentJavaオブジェクトとそのすべてのコンテンツは、回転して破棄されませんが、ビュー再作成されます。それがonCreatedView()再び呼び出されます。これは基本的に、ActivitiesAndroid 1.0以降で動作するはずの方法です。それを使うのが「怠惰」だとは思いませんし、使うのも「適切」ではないと思います。実際、なぜそれがデフォルトではないのか、なぜあなたがそれをオフにしたいのか、私にはわかりません。
Timmmm 2012

24
「バックスタックのフラグメントで動作しないのはなぜですか?」理解しにくいです。しかし、私はばかげているかもしれません:(
HGPB

13
@dierreアクティビティはさまざまな方法で破棄できます。たとえば、「戻る」をクリックすると、アクティビティは破棄されます。「ホーム」をクリックすると、アクティビティが停止し、将来、メモリが不足すると破棄される可能性があります。保持されたFragmentは、構成変更が行われた場合にのみ保持され、基になるアクティビティは破棄されてすぐに再作成されます。アクティビティが破棄される他のすべてのケースでは、保持されているフラグメントも破棄されます。
Alex Lockwood 2013年

3
@AlexLockwoodあなたは次のことを確認してくださいすることができますにもかかわらずsetRetainInstance(true)使用され、一つはまだしなければならない、独自の永続性(実装するsavedInstanceStateすべてのシナリオを処理できるようにするか、そうでない場合に):例えば「ホームキー、回転、アプリのバックには」コンストラクタで私のフラグメントを再現します呼び出し、すべての状態変数を失います。私はAsyncTaskasメンバー変数を持っているので、保持したいので、それを機能させたい場合は、タスクを停止し、状態を保存し、ユーザーが戻ったときに再開するよう強制されます。したがって、全体として、これはローテーションを支援するための迅速な方法にすぎませんが、それ以外の場合は一般的には役に立ちません。
TWiStErRob

28

setRetaininstanceactivity、への呼び出し中にインスタンスが保存されるため、設定の変更によりが破棄されて再作成された場合にのみ役立ちますonRetainNonConfigurationInstance。つまり、デバイスを回転すると、保持されたフラグメントはそこに残ります(破壊および再作成されません)。ただし、ランタイムがリソースを再利用するためにアクティビティを強制終了しても、何も残りません。戻るボタンを押してアクティビティを終了すると、すべてが破棄されます。

通常、この機能を使用して、向きを変更する時間を保存します。たとえば、サーバーからたくさんのビットマップをダウンロードしていて、それぞれが1MBであるとしましょう。Fragmentビットマップを保持して作成し、それをマネージャーに追加してを呼び出しsetRetainInstanceます。画面の向きが変わっても、すべてのビットマップが残っています。


「データのみ」のフラグメント(ウィジェットなし)をビットマップのホルダーと同じように作成しますか、またはこれらのフラグメントにウィジェットを含めることもできますか?フラグメントにコンテキスト/アクティビティに関連する何かが含まれている場合にメモリリークが発生する危険性について読みました
hgoebl

フレームワークはmActivity参照をクリアします。しかし、この場合、ランタイムがフラグメントインスタンスのウィジェットもクリアするかどうかはわかりません。ぜひお試しいただくか、ソースコードをご覧ください。
suitianshi

setRetaininstanceを使用できる良い例
Mu Sa

12

SetRetainInstance(true)を使用すると、フラグメントの並べ替えが可能になります。そのメンバーは、ローテーションなどの構成変更中に保持されます。ただし、アクティビティがバックグラウンドで強制終了されると、強制終了される可能性があります。バックグラウンドで含まれているアクティビティがシステムによって強制終了された場合、onSaveInstanceStateを適切に処理したシステムによって、instanceStateが保存されます。つまり、onSaveInstanceStateは常に呼び出されます。SetRetainInstanceがtrueでフラグメント/アクティビティがまだ終了していない場合、onCreateViewは呼び出されませんが、終了して戻そうとした場合は呼び出されます。

ここでは、Androidのアクティビティ/フラグメントが役立つことを分析します。 http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html


7
画面を回転すると、保持されたフラグメントでonCreateViewが再び呼び出されるのが確実にわかります。
2015

このリンクはあなた自身のブログですか?その場合は、それを明確にする必要があります。
Flexo

4

setRetainInstance()-非推奨

フラグメントバージョン1.3.0-alpha01として

FragmentsのsetRetainInstance()メソッドは非推奨になりました。ViewModelの導入により、開発者は、アクティビティ、フラグメント、およびナビゲーショングラフに関連付けることができる状態を保持するための特定のAPIを使用できます。これにより、開発者は保持されていない通常のFragmentを使用し、保持したい特定の状態を個別に保持し、保持された状態(つまり、ViewModelのコンストラクター)の単一の作成と破棄の有用なプロパティを維持しながら、リークの一般的な原因を回避できます。そしてそれが受け取るonCleared()コールバック)。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.