フラグメント トランザクション

実行時に、FragmentManager はユーザーの操作に応じて、フラグメントに対する追加、削除、置き換えなどのアクションを実行できます。commit するフラグメント変更の各セットは「トランザクション」と呼ばれます。トランザクション内で行う処理は、FragmentTransaction クラスで提供される API を使用して指定できます。アクションが複数ある場合は、1 つのトランザクションにグループ化することができます。たとえば、1 つのトランザクションで複数のフラグメントの追加や置き換えを行えます。このグループ化は、(たとえばビューが分割されて)複数の兄弟フラグメントが 1 つの画面に表示されている場合に便利です。

各トランザクションをバックスタック(FragmentManager によって管理される)に保存すると、ユーザーはフラグメントの変更を元に戻せるようになります。これは、アクティビティを逆方向に操作するのと同じです。

FragmentTransaction のインスタンスを FragmentManager から取得するには beginTransaction() を呼び出します。次の例をご覧ください。

KotlinJava
val fragmentManager = ...
val fragmentTransaction = fragmentManager.beginTransaction()
FragmentManager fragmentManager = ...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

FragmentTransaction の最後の呼び出しでは、トランザクションを commit する必要があります。commit() 呼び出しでは、トランザクションにすべてのオペレーションが追加されたことが FragmentManager に通知されます。

KotlinJava
val fragmentManager = ...
// The fragment-ktx module provides a commit block that automatically
// calls beginTransaction and commit for you.
fragmentManager
.commit {
   
// Add operations here
}
FragmentManager fragmentManager = ...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

// Add operations here

fragmentTransaction
.commit();

フラグメントの状態の変化の並べ替え

FragmentTransactionsetReorderingAllowed(true) を使用する必要があります。

KotlinJava
supportFragmentManager.commit {
   
...
    setReorderingAllowed
(true)
}
FragmentManager fragmentManager = ...
fragmentManager
.beginTransaction()
   
...
   
.setReorderingAllowed(true)
   
.commit();

動作の互換性を確保するため、並べ替えフラグはデフォルトで有効になっていません。 ただし、FragmentManagerFragmentTransaction を適切に実行できるようにする場合、特にバックスタック上で動作してアニメーションや遷移を実行する場合は、このフラグが必要です。このフラグを有効にすると、複数のトランザクションが同時に実行された場合、中間フラグメント(追加されてすぐに置き換えられるフラグメント)にライフサイクルの変更が行われず、アニメーションや遷移が実行されなくなります。このフラグは、トランザクションの最初の実行と、popBackStack() によるトランザクションの逆方向の操作に影響することに注意してください。

フラグメントの追加と削除

FragmentManager にフラグメントを追加するには、トランザクションで add() を呼び出します。このメソッドは、フラグメントのコンテナの ID と、追加するフラグメントのクラス名を受け取ります。追加されたフラグメントは RESUMED 状態に移行します。コンテナはビュー階層の一部である FragmentContainerView にすることを強くおすすめします。

ホストからフラグメントを削除するには、remove() を呼び出し、findFragmentById() または findFragmentByTag() でフラグメント マネージャーから取得したフラグメント インスタンスを渡します。フラグメントのビューが以前にコンテナに追加されていた場合、この時点でビューはコンテナから削除されます。削除されたフラグメントは DESTROYED 状態に移行します。

コンテナの既存のフラグメントを、指定した新しいフラグメント クラスのインスタンスに置き換えるには、replace() を使用します。replace() の呼び出しは、コンテナ内のフラグメントで remove() を呼び出し、同じコンテナに新しいフラグメントを追加することと同じです。

次のコード スニペットで、フラグメントを別のフラグメントに置き換える方法を示します。

KotlinJava
// Create new fragment
val fragmentManager = // ...

// Create and commit a new transaction
fragmentManager
.commit {
    setReorderingAllowed
(true)
   
// Replace whatever is in the fragment_container view with this fragment
    replace
<ExampleFragment>(R.id.fragment_container)
}
// Create new fragment and transaction
FragmentManager fragmentManager = ...
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction
.setReorderingAllowed(true);

// Replace whatever is in the fragment_container view with this fragment
transaction
.replace(R.id.fragment_container, ExampleFragment.class, null);

// Commit the transaction
transaction
.commit();

この例では、R.id.fragment_container で識別されるレイアウト コンテナ内にフラグメントが存在している場合、そのフラグメントを ExampleFragment の新しいインスタンスに置き換えます。

デフォルトでは、FragmentTransaction に行った変更はバックスタックに追加されません。これらの変更を保存するには、FragmentTransactionaddToBackStack() を呼び出します。詳しくは、フラグメント マネージャーをご覧ください。

commit の非同期性

commit() を呼び出しても、トランザクションはすぐに実行されませんが、可能な限り早くメイン UI スレッドで実行されるようにスケジュールされます。ただし必要であれば、commitNow() を呼び出して、UI スレッドでフラグメント トランザクションをすぐに実行できます。

commitNowaddToBackStack と互換性がありません。commit() 呼び出しで送信された保留中の FragmentTransactions のうち、まだ実行されていないものをすべて実行するには、executePendingTransactions() を呼び出します。このアプローチは、addToBackStack と互換性があります。

ほとんどのユースケースでは、commit() があれば十分です。

オペレーションの順序の重要性

FragmentTransaction 内でオペレーションを実行する順序は、setCustomAnimations() を使用している場合には特に重要です。このメソッドは、指定されたアニメーションを、それに続くすべてのフラグメント オペレーションに適用します。

KotlinJava
supportFragmentManager.commit {
    setCustomAnimations
(enter1, exit1, popEnter1, popExit1)
    add
<ExampleFragment>(R.id.container) // gets the first animations
    setCustomAnimations
(enter2, exit2, popEnter2, popExit2)
    add
<ExampleFragment>(R.id.container) // gets the second animations
}
getSupportFragmentManager().beginTransaction()
       
.setCustomAnimations(enter1, exit1, popEnter1, popExit1)
       
.add(R.id.container, ExampleFragment.class, null) // gets the first animations
       
.setCustomAnimations(enter2, exit2, popEnter2, popExit2)
       
.add(R.id.container, ExampleFragment.class, null) // gets the second animations
       
.commit()

フラグメントのライフサイクルに対する制限

FragmentTransactions は、トランザクションのスコープ内で追加された個々のフラグメントのライフサイクル状態に影響を与える可能性があります。FragmentTransaction を作成するとき、setMaxLifecycle() は指定されたフラグメントの最大の状態を設定します。たとえば、ViewPager2setMaxLifecycle() を使用して、画面外のフラグメントを STARTED 状態に制限します。

フラグメントのビューの表示と非表示の切り替え

コンテナに追加されたフラグメントのビューの表示と非表示を切り替えるには、FragmentTransaction メソッドの show()hide() を使用します。 これらのメソッドは、フラグメントのライフサイクルに影響を与えずにフラグメントのビューの表示方法を設定します。

フラグメント内のビューの表示を切り替えるためにフラグメント トランザクションを使用する必要はありませんが、こうしたメソッドは、表示状態の変更をバックスタック上のトランザクションに関連付ける場合に便利です。

フラグメントのアタッチとデタッチ

FragmentTransaction メソッド detach() は UI からフラグメントをデタッチして、そのビュー階層を破棄します。フラグメントは、バックスタックに配置されたときと同じ状態(STOPPED)を維持します。つまり、フラグメントは UI から削除されましたが、フラグメント マネージャーによってまだ管理されています。

attach() メソッドは、以前にデタッチされたフラグメントを再アタッチします。これにより、ビュー階層が再作成され、UI にアタッチされて表示されます。

FragmentTransaction は 1 つのアトミックな操作セットとして扱われるため、同じトランザクション内の同じフラグメント インスタンスで detachattach の両方を呼び出すと、実質的に互いと相殺されます。これにより、フラグメントの UI が破棄されて即座に再作成されるのを回避できます。フラグメントをデタッチしてすぐに再アタッチするときに commit() を使用している場合は、個別のトランザクションを executePendingOperations() で区切って使用します。