런타임 시 FragmentManager
는 사용자 상호작용의 응답으로 프래그먼트와 함께 작업을 추가하거나 삭제, 교체하는 등 기타 작업을 할 수 있습니다. 커밋하는 각 프래그먼트 변경사항 집합을 트랜잭션이라고 합니다. 개발자는 FragmentTransaction
클래스에 의해 제공되는 API를 사용하여 이 트랜잭션 내에서 실행할 작업을 지정할 수 있습니다. 여러 작업을 단일 트랜잭션으로 그룹화할 수 있습니다. 예를 들어 한 트랜잭션에서 여러 개의 프래그먼트를 추가하거나 바꿀 수 있습니다. 이 같은 그룹화는 분할 뷰를 사용할 때처럼 한 화면에 여러 개의 동위 프래그먼트가 표시되는 경우에 유용합니다.
FragmentManager
에서 관리하는 백 스택에 각 트랜잭션을 저장할 수 있습니다. 그렇게 하면 사용자가 활동에서 뒤로 이동하는 것처럼 프래그먼트 변경사항에서 뒤로 이동할 수 있습니다.
다음 예에 나와 있는 것처럼 beginTransaction()
을 호출하여 FragmentManager
에서 FragmentTransaction
의 인스턴스를 가져올 수 있습니다.
Kotlin
val fragmentManager = ... val fragmentTransaction = fragmentManager.beginTransaction()
자바
FragmentManager fragmentManager = ... FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
각 FragmentTransaction
의 마지막 호출은 트랜잭션을 커밋해야 합니다.
commit()
호출은 FragmentManager
에 모든 작업이 트랜잭션에 추가되었음을 알려줍니다.
Kotlin
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();
프래그먼트 상태 변경의 재정렬 허용
각 FragmentTransaction
은 setReorderingAllowed(true)
를 사용해야 합니다.
Kotlin
supportFragmentManager.commit { ... setReorderingAllowed(true) }
자바
FragmentManager fragmentManager = ... fragmentManager.beginTransaction() ... .setReorderingAllowed(true) .commit();
동작 호환성을 위해 재정렬 플래그는 기본적으로 사용되지 않습니다.
그러나 FragmentManager
에 FragmentTransaction
을 올바로 실행할 수 있도록 허용해야 하며, 프래그먼트 관리자가 백 스택에서 동작하고 애니메이션과 전환을 실행하는 경우에는 더욱 그러합니다. 이 플래그를 사용 설정하면 여러 트랜잭션이 함께 실행될 때 중간 프래그먼트(즉, 추가된 직후 교체된 프래그먼트)에 수명 주기 변경이 발생하지 않거나 애니메이션 또는 전환이 실행되지 않습니다. 참고로, 이 플래그는 트랜잭션의 초기 실행은 물론, popBackStack()
으로 트랜잭션을 반전시키는 작업에도 영향을 미칩니다.
프래그먼트 추가 및 삭제
FragmentManager
에 프래그먼트를 추가하려면 트랜잭션에서 add()
를 호출합니다. 이 메서드는 프래그먼트의 컨테이너 ID와 추가하려는 프래그먼트의 클래스 이름을 수신합니다. 추가된 프래그먼트는 RESUMED
상태로 전환됩니다. 컨테이너를 뷰 계층 구조의 일부인 FragmentContainerView
로 사용하는 것이 좋습니다.
호스트에서 프래그먼트를 삭제하려면 remove()
를 호출하고 findFragmentById()
또는 findFragmentByTag()
를 통해 프래그먼트 관리자에서 가져온 프래그먼트 인스턴스를 전달합니다.
프래그먼트의 뷰가 이전에 컨테이너에 추가되었다면, 이 시점에서 이 뷰가 컨테이너에서 삭제됩니다. 삭제된 프래그먼트는 DESTROYED
상태로 전환됩니다.
replace()
를 사용하여 컨테이너의 기존 프래그먼트를 개발자가 제공할 새 프래그먼트 클래스의 인스턴스로 바꿀 수 있습니다. replace()
를 호출하는 것은 컨테이너의 프래그먼트와 함께 remove()
를 호출하거나 동일한 컨테이너에 새 프래그먼트를 추가하는 것과 같습니다.
다음 코드 스니펫은 특정 프래그먼트를 다른 프래그먼트로 바꾸는 방법을 보여줍니다.
Kotlin
// 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();
이 예에서 ExampleFragment
의 새 인스턴스는 현재 R.id.fragment_container
로 식별된 레이아웃 컨테이너에 있는 프래그먼트(있는 경우)를 바꿉니다.
기본적으로 FragmentTransaction
에서 변경한 내용은 백 스택에 추가되지 않습니다. 이러한 변경사항을 저장하려면 FragmentTransaction
에서 addToBackStack()
를 호출하면 됩니다. 자세한 내용은 프래그먼트 관리자를 참조하세요.
커밋이 비동기식임
commit()
을 호출하더라도 트랜잭션이 즉시 실행되지는 않습니다. 대신 트랜잭션이 가능한 빨리 기본 UI 스레드에서 실행되도록 예약됩니다. 그러나 필요한 경우 commitNow()
를 호출하여 UI 스레드에서 프래그먼트 트랜잭션을 즉시 실행할 수 있습니다.
참고로, commitNow
는 addToBackStack
과 호환되지 않습니다. 또는 commit()
호출로 제출된 모든 대기중 FragmentTransactions
중에서 executePendingTransactions()
을 호출해 아직 실행되지 않은 것을 실행할 수 있습니다. 이 방법은 addToBackStack
에도 적용 가능합니다.
대부분의 사용 사례에서는 commit()
만 있으면 됩니다.
작업 순서가 중요함
특히 setCustomAnimations()
를 사용할 경우 FragmentTransaction
내에서의 작업 순서가 중요합니다. 이 메서드는 메서드를 따르는 모든 프래그먼트 작업에 지정된 애니메이션을 적용합니다.
Kotlin
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()
은 주어진 프래그먼트의 최대 상태를 설정합니다. 예를 들어 ViewPager2
는 setMaxLifecycle()
을 사용하여, 화면을 벗어난 프래그먼트를 STARTED
상태로 제한합니다.
프래그먼트의 뷰 표시 및 숨기기
FragmentTransaction
메서드 show()
및 hide()
를 사용하여 컨테이너에 추가된 프래그먼트의 뷰를 표시하거나 숨길 수 있습니다.
이러한 메서드는 프래그먼트의 수명 주기에 영향을 주지 않는 상태에서 프래그먼트 뷰의 공개 상태를 설정합니다.
프래그먼트 내에서 뷰 가시성을 전환하는 데 프래그먼트 트랜잭션을 사용할 필요가 없기는 하지만, 공개 상태 변경을 백 스택의 트랜잭션에 연결하려는 경우 이러한 메서드가 유용합니다.
프래그먼트 연결 및 분리
FragmentTransaction
메서드 detach()
는 프래그먼트를 UI에서 분리하고 뷰 계층 구조를 소멸시킵니다. 프래그먼트는 백 스택에 배치될 때와 동일한 상태(STOPPED
)로 유지됩니다.
즉, 프래그먼트는 UI에서 삭제되었지만 프래그먼트 관리자에 의해 계속 관리됩니다.
attach()
메서드는 이전에 분리된 프래그먼트를 다시 연결합니다.
그러면 뷰 계층 구조가 다시 생성되고 UI에 연결되어 표시됩니다.
FragmentTransaction
이 작업의 단일 원자형 집합으로 처리되므로, 동일한 트랜잭션의 동일한 프래그먼트 인스턴스에서 detach
와 attach
를 모두 호출하면 사실상 서로 상쇄됩니다. 따라서 프래그먼트 UI가 소멸되고 즉시 재생성되는 것이 방지됩니다. commit()
을 사용할 때 프래그먼트를 분리하고 바로 다시 연결하려면 executePendingOperations()
로 분리된 개별 트랜잭션을 사용하세요.