[解決済み】popBackStack()とreplace()の操作はどう違うのですか?
質問
私のアプリケーションでフラグメントを管理する際に、不思議な動作に遭遇しました。
私のアプリケーションの一般的な流れは、ユーザーが何らかの方法でフラグメントAとインタラクションを行うと、フラグメントBが
fragmentTransaction.replace()
(これはすべてのケースで起こる)。 フラグメントBを表示するとき、フラグメントAをバックスタックに追加します。そして、ユーザーがフラグメントBのバックボタンを押すと、フラグメントAはバックスタックからポップアップして再び表示されるのです。
それはいいのですが、今日、フラグメントBから
fragmentTransaction.replace()
フラグメントBは、現在バックスタックにあるフラグメントAと同じインスタンスに置き換わります。
それ自体は問題ないのですが、フラグメントAからフラグメントBに戻るときにおかしな動作が発生します。
fragmentTransaction.replace()
は、その
onCreate()
メソッドは呼び出されません。
しかし、バックスタックからフラグメントAをポップし、フラグメントBと入れ替えると
onCreate()
メソッドが実行されます。 これはなぜでしょうか?
フラグメントAとフラグメントBのインスタンスは、ホストアクティビティが起動した時点ですべて生成されることに注意してください。
明確化のために編集します。 この場合
onCreate()
が2回目に呼ばれるのは以下の通りです。フラグメントAをアタッチする => フラグメントBに置き換えて、フラグメントAをバックスタックに追加する => フラグメントAを
popBackStack()
=> Fragment Aを再びFragment Bに置き換える。
どのように解決するのですか?
replace()
は、2つのことを行います。
- 現在追加されているフラグメント(A)を、指定したコンテナ(C)から削除する。
- 同じコンテナに新しいフラグメント(B)を追加する
この2つの操作が、Backstackのレコード/トランザクションとして保存されるものです。なお、フラグメントAは
created
状態になり、そのビューは破棄されます。
現在
popBackStack()
は、BackStackに追加した最後のトランザクションを取り消します。
この場合、2ステップになります。
- CからBを削除する
- CにAを追加
この後、フラグメントBは次のようになります。
detached
そして、もしあなたがそれへの参照を保持していなかったならば、それはガベージコレクションされるでしょう。
質問の最初の部分に対する答えですが、この質問には
onCreate()
の呼び出しは、FragmentB が
created
の状態になります。そして、質問の後半部分の答えは、もう少し長くなります。
まず、重要なのは、実際に
Fragments
をBackstackに追加します。
FragmentTransactions
. つまり、「フラグメントBに置き換えて、フラグメントAをバックスタックに追加する」と考えたとき、実際にはこの操作全体をバックスタックに追加していることになります - つまり
置換
この置換は、Aを削除し、Bを追加するという2つのアクションで構成されています。
そして、次のステップは、この置換を含むトランザクションをポップすることです。つまり、FragmentAをpopしているのではなく、"remove A, add B"を反転させて、"remove B, add A"としているのです。
最後のステップでは、FragmentManagerが認識しているBは存在しないので、最後のステップでAをBに置き換えて追加すると、Bはその初期のライフサイクルメソッドを通過する必要があります。
onAttach()
と
onCreate()
.
以下のコードは、その様子を示しています。
FragmentManager fm = getFragmentManager();
FragmentA fragmentA = new FragmentA();
FragmentB fragmentB = new FragmentB();
// 1. Show A
fm.beginTransaction()
.add(fragmentA, R.id.container)
.commit();
// 2. Replace A with B
// FragmentManager keeps reference to fragmentA;
// it stays attached and created; fragmentB goes
// through lifecycle methods onAttach(), onCreate()
// and so on.
fm.beginTransaction()
.replace(fragmentB, R.id.container)
.addToBackstack(null)
.commit();
// 2'. Alternative to replace() method
fm.beginTransaction()
.remove(fragmentA)
.add(fragmentB, R.id.container)
.addToBackstack(null)
.commit();
// 3. Reverse (2); Result - A is visible
// What happens:
// 1) fragmentB is removed from container, it is detached now;
// FragmentManager doesn't keep reference to it anymore
// 2) Instance of FragmentA is placed back in the container
// Now your Backstack is empty, FragmentManager is aware only
// of FragmentA instance
fm.popBackStack();
// 4. Show B
// Since fragmentB was detached, it goes through its early
// lifecycle methods: onAttach() and onCreate().
fm.beginTransaction()
.replace(fragmentB, R.id.container)
.addToBackstack(null)
.commit();
関連
-
[解決済み】非閉鎖文字リテラルエラー
-
[解決済み] add()、replace()、addToBackStack()の相違点
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Bitmapオブジェクトに画像を読み込む際にOutOfMemoryが発生する問題
-
[解決済み] なぜフラグメントなのか、そしてアクティビティの代わりにフラグメントを使用するのはどんなときか?
-
[解決済み] フラグメントのインスタンス状態をバックスタックに正しく保存する方法は?
-
[解決済み] ViewPagerとフラグメント - フラグメントの状態を保存する正しい方法は何ですか?
-
[解決済み] FragmentのsetRetainInstance(boolean)を理解する。
-
[解決済み】「px」、「dip」、「dp」、「sp」の違いは?
-
[解決済み】フラグメント内のXML onClickを使用して、ボタンのクリックを処理する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Java、"変数名 "を変数に解決することができない
-
[解決済み】Android Studioでタスク :app:compileDebugJavaWithJavac の実行に失敗しました。
-
[解決済み】Mockitoでモックからチェックされた例外を投げる
-
[解決済み】keytoolエラー 鍵屋が改ざんされたか、パスワードが不正確だった場合
-
[解決済み】Javaを使用するSelenium - ドライバの実行ファイルのパスは、webdriver.gecko.driverシステムプロパティで設定する必要があります。
-
[解決済み】Javaで文字列をコピーするにはどうしたらいいですか?
-
[解決済み】Javaメソッドスタブ
-
[解決済み】ソースルート外のJavaファイル intelliJ
-
[解決済み】 executeQuery()でデータ操作文が発行できない。)
-
[解決済み】バックスタックで前のフラグメントに戻るプログラム