프래그먼트 수명 주기

Fragment 인스턴스에는 고유한 수명 주기가 있습니다. 사용자가 앱을 탐색하거나 앱과 상호작용할 때 프래그먼트는 화면에서 추가 또는 삭제되거나 화면에 들어가고 나오면서 수명 주기의 여러 상태 간에 전환하게 됩니다.

수명 주기를 관리하기 위해 FragmentLifecycleOwner를 구현하여, getLifecycle() 메서드를 통해 액세스할 수 있는 Lifecycle 객체를 노출합니다.

가능한 각 Lifecycle 상태는 Lifecycle.State 열거형으로 표시됩니다.

Lifecycle 위에 Fragment를 빌드하면 수명 주기 인식 구성요소로 수명 주기 처리에 사용할 수 있는 기법과 클래스를 사용할 수 있습니다. 예를 들어 수명 주기 인식 구성요소를 사용하여 기기의 위치를 화면에 표시할 수 있습니다. 이 구성요소는 프래그먼트가 활성 상태가 되면 자동으로 수신 대기를 시작하고 프래그먼트가 비활성 상태로 전환되면 자동으로 수신 대기를 중지할 수 있습니다.

LifecycleObserver를 사용하는 것의 대안으로, Fragment 클래스에는 프래그먼트 수명 주기의 각 변경에 대응하는 콜백 메서드가 포함되어 있습니다. onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy()가 포함되어 있습니다.

프래그먼트의 뷰에는 프래그먼트의 Lifecycle의 뷰와 독립적으로 관리되는 별도의 Lifecycle이 있습니다. 프래그먼트는 getViewLifecycleOwner() 또는 getViewLifecycleOwnerLiveData()를 사용하여 액세스할 수 있는, 관련 뷰의 LifecycleOwner를 관리합니다. 뷰의 Lifecycle에 액세스할 수 있는 권한이 있으면 수명 주기 인식 구성요소가 프래그먼트의 뷰가 존재하는 동안에만 작업(예: 화면 표시 전용의 LiveData 관찰)해야 하는 상황에 유용합니다.

이 항목에서는 Fragment 수명 주기에 관해 자세히 논의하고, 프래그먼트의 수명 주기 상태를 확인하는 일부 규칙을 설명하며, Lifecycle 상태와 프래그먼트 수명 주기 콜백 간의 관계를 표시하는 방법을 보여줍니다.

프래그먼트 및 프래그먼트 관리자

프래그먼트는 인스턴스화되면 INITIALIZED 상태에서 시작됩니다. 프래그먼트가 프래그먼트의 나머지 수명 주기를 전환하도록 하려면 프래그먼트를 FragmentManager에 추가해야 합니다. FragmentManager가 프래그먼트가 어떤 상태여야 하는지 확인한 다음 그 상태로 전환하는 일을 담당합니다.

프래그먼트 수명 주기를 벗어나면 FragmentManager는 프래그먼트를 호스트 활동에 연결하고 프래그먼트가 더 이상 사용되지 않을 때는 프래그먼트를 분리하는 작업도 합니다. Fragment 클래스에는 두 가지 콜백 메서드 onAttach()onDetach()가 있습니다. 이러한 메서드는 관련 이벤트 중 하나가 발생했을 때 작업을 위해 재정의할 수 있습니다.

onAttach() 콜백은 프래그먼트가 FragmentManager에 추가되었을 때 호스트 활동에 연결되면 호출됩니다. 이 시점에 프래그먼트는 활성 상태이며 FragmentManager가 수명 주기 상태를 관리하고 있습니다. 이 시점에서 findFragmentById() 같은 FragmentManager 메서드가 이 프래그먼트를 반환합니다.

onAttach()는 항상 수명 주기 상태 변경 전에 호출됩니다.

onDetach() 콜백은 프래그먼트가 FragmentManager에서 삭제되었을 때 호스트 활동에서 분리되면 호출됩니다. 프래그먼트가 더 이상 활성 상태가 아니므로 findFragmentById()를 사용하여 더 이상 검색할 수 없습니다.

onDetach()수명 주기 상태 변경 후에 항상 호출됩니다.

참고로, 이러한 콜백은 FragmentTransaction 메서드 attach()detach()와 연관이 없습니다. 이러한 메서드에 관한 자세한 내용은 프래그먼트 트랜잭션을 참조하세요.

프래그먼트 수명 주기 상태 및 콜백

프래그먼트의 수명 주기 상태를 결정할 때 FragmentManager는 다음 사항을 고려합니다.

  • 프래그먼트의 최대 상태는 FragmentManager에 의해 결정됩니다. 프래그먼트는 FragmentManager의 상태를 벗어나 진행될 수 없습니다.
  • FragmentTransaction의 일부로 setMaxLifecycle()을 사용하여 프래그먼트에 최대 수명 주기 상태를 설정할 수 있습니다 .
  • 프래그먼트의 수명 주기 상태는 상위 요소보다 클 수 없습니다. 예를 들어 상위 프래그먼트 또는 상위 활동은 하위 프래그먼트보다 먼저 시작해야 합니다. 마찬가지로 하위 프래그먼트는 상위 프래그먼트 또는 상위 활동보다 먼저 중지되어야 합니다.
프래그먼트 수명 주기 상태와 이 상태가 프래그먼트의 수명 주기 콜백 및 프래그먼트의 뷰 수명 주기와 갖는 관계
그림 1. 프래그먼트 Lifecycle 상태와 프래그먼트의 수명 주기 콜백 및 프래그먼트의 뷰 Lifecycle와의 관계

그림 1은 프래그먼트의 각 Lifecycle 상태와 그 상태가 프래그먼트의 수명 주기 콜백은 물론 프래그먼트의 뷰 Lifecycle과 어떤 관련이 있는지를 보여줍니다.

프래그먼트는 수명 주기를 거치며 상태를 따라 위아래로 이동합니다. 예를 들어 백 스택 상단에 추가된 프래그먼트는CREATED에서 STARTED를 거쳐 RESUMED까지 위로 이동합니다. 반대로 프래그먼트가 백 스택에서 사라진 경우 RESUMED에서 STARTED를 거쳐 CREATED로, 최종적으로 DESTROYED 상태가 될 때까지 아래로 이동합니다.

상향 상태 전환

프래그먼트는 수명 주기 상태를 통해 위로 이동할 때 먼저 새 상태와 관련된 수명 주기 콜백을 호출합니다. 이 콜백이 끝나면 관련 Lifecycle.Event가 프래그먼트의 Lifecycle에 의해 관찰자로 보내집니다. 인스턴스화된 경우 그다음에는 프래그먼트의 뷰 Lifecycle에 의해 보내집니다.

프래그먼트 CREATED

프래그먼트가 CREATED 상태에 도달하면, 이미 프래그먼트는 FragmentManager에 추가되고 onAttach() 메서드가 호출된 상태입니다.

이 위치는 프래그먼트의 SavedStateRegistry를 통해 프래그먼트 자체와 연결된 저장 상태를 복원하는 데 적절합니다. 참고로, 이 시점에는 프래그먼트의 뷰가 생성되지 않았으며 프래그먼트의 뷰와 관련된 모든 상태는 뷰가 생성된 이후에만 복원해야 합니다.

이 전환은 onCreate() 콜백을 호출합니다. 이 콜백은 이전에 onSaveInstanceState()에 의해 저장된 상태를 포함하는 savedInstanceState Bundle 인수도 수신합니다. 프래그먼트가 처음 생성될 때는 savedInstanceStatenull 값을 갖지만 개발자가 onSaveInstanceState()을 재정의하지 않더라도 이후 생성에서는 항상 null이 아닙니다. 자세한 내용은 프래그먼트와 함께 상태 저장을 참조하세요.

프래그먼트 CREATED 및 뷰 INITIALIZED

Fragment가 유효한 View 인스턴스를 제공하는 경우에만 프래그먼트의 뷰 Lifecycle이 생성됩니다. 대부분의 경우 @LayoutId(적절한 시간에 뷰를 자동으로 확장함)를 사용하는 프래그먼트 생성자를 사용할 수 있습니다. 또한 onCreateView()를 재정의하여 프로그래매틱 방식으로 프래그먼트의 뷰를 확장하거나 만들 수 있습니다.

프래그먼트의 뷰가 null이 아닌 View로 인스턴스화된 경우(또는 이 경우에만) 그 View는 프래그먼트에 설정되고, getView()를 사용하여 검색할 수 있습니다. 그런 다음 getViewLifecycleOwnerLiveData()가 프래그먼트의 뷰에 대응하는 새로운 INITIALIZED LifecycleOwner로 업데이트됩니다. 이 시점에서는 onViewCreated() 수명 주기 콜백도 호출됩니다.

이 위치는 뷰의 초기 상태를 설정하고, 프래그먼트의 뷰를 업데이트하는 콜백을 갖는 LiveData 인스턴스를 관찰하며, 프래그먼트의 뷰에서 RecyclerView 또는 ViewPager2 인스턴스에 어댑터를 설정하기에 적합합니다.

프래그먼트 및 뷰 CREATED

프래그먼트의 뷰가 생성되면 이전 뷰 상태(있는 경우)가 복원되고 뷰의 LifecycleCREATED 상태로 전환됩니다. 또한 뷰 수명 주기 소유자는 ON_CREATE 이벤트를 관찰자로 보냅니다. 여기에서 프래그먼트의 뷰와 관련된 모든 추가 상태를 복원해야 합니다.

이 전환에서는 onViewStateRestored() 콜백도 호출합니다.

프래그먼트 및 뷰 STARTED

수명 주기 인식 구성요소를 프래그먼트의 STARTED 상태와 연결하는 것이 좋습니다. 이 상태와 연결하면 프래그먼트의 뷰(생성된 경우)를 사용할 수 있고 프래그먼트의 하위 FragmentManager에서 FragmentTransaction을 안전하게 실행할 수 있기 때문입니다. 프래그먼트의 뷰가 null이 아니면 프래그먼트의 LifecycleSTARTED로 전환된 직후 프래그먼트의 뷰 LifecycleSTARTED로 전환됩니다.

프래그먼트가 STARTED가 되면 onStart() 콜백이 호출됩니다.

프래그먼트 및 뷰 RESUMED

프래그먼트가 표시되면 모든 Animator 효과와 Transition 효과가 완료되어 프래그먼트를 사용자 상호작용에 사용할 수 있습니다. 프래그먼트의 LifecycleRESUMED 상태로 전환되고 onResume() 콜백이 호출됩니다.

RESUMED로 전환된 것은 사용자가 이제 프래그먼트와 상호작용할 수 있음을 나타내는 적절한 신호입니다. RESUMED가 아닌 프래그먼트는 뷰에 포커스를 수동으로 설정하거나 입력 메서드 공개 상태를 처리하려고 시도해서는 안 됩니다.

하향 상태 전환

프래그먼트가 하위 수명 주기 상태 방향으로 아래로 이동하면 관련 Lifecycle.Event가 프래그먼트의 뷰 Lifecycle에 의해 관찰자로 보내집니다. 인스턴스화된 경우 그다음에는 프래그먼트의 Lifecycle에 의해 보내집니다. 프래그먼트의 수명 주기 이벤트가 보내지면 프래그먼트가 관련 수명 주기 콜백을 호출합니다.

프래그먼트 및 뷰 STARTED

사용자가 프래그먼트를 벗어나기 시작할 때에도 프래그먼트가 표시된 상태이면 프래그먼트와 관련 뷰의 Lifecycle은 다시 STARTED 상태로 전환되고 관찰자에 ON_PAUSE 이벤트를 보냅니다. 그런 다음 프래그먼트는 onPause() 콜백을 호출합니다.

프래그먼트 및 뷰 CREATED

프래그먼트가 더 이상 표시되지 않으면 프래그먼트와 관련 뷰의 LifecycleCREATED 상태로 전환되고 관찰자에 ON_STOP 이벤트를 보냅니다. 이 상태 전환은 중지 중인 상위 활동 또는 상위 프래그먼트에 의해 트리거될 뿐 아니라, 상위 활동 또는 상위 프래그먼트의 상태 저장에 의해서도 트리거됩니다. 이 동작으로 프래그먼트의 상태가 저장되기 전에 ON_STOP 이벤트가 호출됩니다. 그렇게 되면 ON_STOP 이벤트가 하위 FragmentManager에서 FragmentTransaction을 안전하게 실행할 수 있는 마지막 지점이 됩니다.

그림 2에 나와 있는 것처럼 onStop() 콜백의 순서와 onSaveInstanceState()를 사용한 상태 저장은 API 수준에 따라 다릅니다. API 28 이전의 모든 API 수준에서는 onSaveInstanceState()onStop() 이전에 호출됩니다. API 수준 28 이상에서는 호출 순서가 반대가 됩니다.

onStop() 및 onSaveInstanceState()의 호출 순서 차이
그림 2. onStop()onSaveInstanceState()의 호출 순서 차이

프래그먼트 CREATED 및 뷰 DESTROYED

나가기 애니메이션과 전환이 모두 완료되고 프래그먼트의 뷰가 창에서 분리되면 프래그먼트의 뷰 LifecycleDESTROYED 상태로 전환되고 ON_DESTROY 이벤트를 관찰자에 보냅니다. 그런 다음 프래그먼트가 onDestroyView() 콜백을 호출합니다. 이 시점에서 프래그먼트의 뷰는 수명 주기의 끝에 도달했으며 getViewLifecycleOwnerLiveData()null 값을 반환합니다.

이때 프래그먼트 뷰의 모든 참조를 삭제해야 합니다. 그래야 프래그먼트의 뷰에서 가비지를 수집할 수 있습니다.

프래그먼트 DESTROYED

프래그먼트가 삭제되거나 FragmentManager가 소멸되면 프래그먼트의 LifecycleDESTROYED 상태로 전환되고 ON_DESTROY 이벤트를 관찰자에 전송합니다. 그런 다음 프래그먼트가 onDestroy() 콜백을 호출합니다. 이 시점에서 프래그먼트는 수명 주기의 끝에 도달한 상태입니다.

추가 리소스

프래그먼트 수명 주기와 관련된 자세한 내용은 다음 추가 리소스를 참조하세요.

가이드

블로그