관리 메뉴

나만을 위한 블로그

[Android] 프래그먼트의 생명주기 본문

Android

[Android] 프래그먼트의 생명주기

참깨빵위에참깨빵_ 2024. 3. 31. 18:27
728x90
반응형

이전 포스팅에서 프래그먼트를 어떻게 구현하는지 간단하게 확인했으니 이제 생명주기를 확인할 차례다.

자체적인 생명주기를 갖기 때문에, 액티비티와 다른 점이 뭔지 생각하면서 보면 좋을 것이다.

 

https://developer.android.com/guide/fragments/lifecycle?hl=ko

 

프래그먼트 수명 주기  |  Android 개발자  |  Android Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 프래그먼트 수명 주기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 각 Fragment 인스턴스에는 고유한

developer.android.com

각 프래그먼트 인스턴스에는 고유한 생명주기가 있다. 유저가 앱을 탐색하거나 상호작용할 때 프래그먼트는 화면에서 추가, 삭제되거나 화면에 들어가고 나오면서 생명주기의 여러 상태 간에 전환하게 된다. 생명주기를 관리하기 위해 프래그먼트는 LifecycleOwner를 구현해서 getLifecycle()을 통해 접근할 수 있는 Lifecycle 객체를 노출한다. 가능한 각 Lifecycle 상태는 Lifecycle.State enum으로 표시된다

- INITIALIZED
- CREATED
- STARTED
- RESUMED
- DESTROYED

Lifecycle 위에 프래그먼트를 빌드하면 생명주기 인식 컴포넌트로 생명주기 처리에 쓸 수 있는 기법, 클래스를 쓸 수 있다...(중략)...LifecycleOwner의 대안으로 프래그먼트 클래스에는 프래그먼트 생명주기의 각 변경에 대응하는 콜백 메서드인 onCreate, onStart, onResume, onPause, onStop, onDestroy가 있다
프래그먼트의 뷰에는 프래그먼트의 Lifecycle의 뷰와 독립적으로 관리되는 별도의 Lifecycle이 있다. 프래그먼트는 getViewLifecycleOwner 또는 getViewLifecycleOwnerLiveData를 써서 접근할 수 있는 관련 뷰의 LifecycleOwner를 관리한다. 뷰의 Lifecycle에 접근할 수 있는 권한이 있으면 생명주기 인식 컴포넌트가 프래그먼트의 뷰가 존재하는 동안에만 작업해야 하는 상황(화면 표시 전용의 LiveData 관찰 등)에 유용하다

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

프래그먼트의 생명주기 상태를 결정할 때 FragmentManager는 다음 사항을 고려한다...(중략)

- 프래그먼트의 생명주기 상태는 상위 요소보다 클 수 없다. 예를 들어 상위 프래그먼트 or 액티비티는 하위 프래그먼트보다 먼저 시작해야 한다. 마찬가지로 하위 프래그먼트는 상위 프래그먼트 or 액티비티보다 먼저 중지돼야 한다

주의 : XML을 사용하는 프래그먼트를 추가할 때 <fragment>를 쓰지 마라. 이걸 쓰면 프래그먼트가 FragmentManager의 상태를 벗어나 이동할 수 있다. 대신 FragmentContainerView를 써서 XML을 쓰는 프래그먼트를 추가하라

 

5가지의 enum을 통해 프래그먼트의 생명주기에 접근할 수 있는 것, 프래그먼트의 생명주기 상태는 프래그먼트를 호스팅하는 액티비티 / 프래그먼트보다 클 수 없다는 것에 주목하면 될 것 같다. 물론 다른 부분도 알아두면 좋을 것이다.

아래 그림은 각 Lifecycle의 상태와 그 상태가 프래그먼트의 생명주기 콜백, 프래그먼트의 뷰 Lifecycle과 어떤 관련이 있는지를 보여준다.

 

 

프래그먼트는 생명주기 상태를 통해 위로 이동할 때, 먼저 새 상태와 관련된 생명주기 콜백을 호출한다.

이 콜백이 끝나면 관련 Lifecycle.Event가 프래그먼트의 Lifecycle에 의해 관찰자로 보내진다. 인스턴스화된 경우 그 다음에는 프래그먼트의 뷰 Lifecycle에 의해 보내진다.

 

프래그먼트 CREATED

 

프래그먼트가 이 상태에 도달하면 프래그먼트는 이미 FragmentManager에 추가되고 onAttach가 호출된 상태다.

여기선 프래그먼트의 SavedStateRegistry를 통해 프래그먼트 자체와 연결된 저장 상태를 복원하는 데 적절하다. 그리고 이 때는 아직 프래그먼트 뷰가 생성되지 않았으며, 이 전환은 onCreate 콜백을 호출한다.

또한 이전에 onSaveInstanceState()로 저장된 상태를 포함하는 Bundle도 받는다. 그리고 프래그먼트가 처음 생성될 때는 savedInstanceState가 null이지만 개발자가 onSaveInstanceState를 재정의하지 않아도 이후 생성에선 항상 null이 아니다.

 

프래그먼트 CREATED 및 뷰 INITIALIZED

 

프래그먼트가 유효한 View 인스턴스를 제공할 때만 프래그먼트의 뷰 Lifecycle이 생성된다.

대부분의 경우 @LayoutId를 사용하는 프래그먼트 생성자를 쓸 수 있고, onCreateView를 재정의해서 프로그래매틱 방식으로 프래그먼트의 뷰를 확장하거나 만들 수 있다.

프래그먼트 뷰가 null이 아닌 View로 인스턴스화된 경우(또는 이 때만) 그 View는 프래그먼트에 설정되고 getView()로 검색할 수 있다. 이 때 onViewCreated도 호출된다.

이 위치에선 뷰의 초기 상태 설정, LiveData 인스턴스 관찰, 프래그먼트 뷰에서 리사이클러뷰 or 뷰페이저2 인스턴스에 어댑터 설정하기 적합하다.

 

프래그먼트 및 뷰 CREATED

 

프래그먼트 뷰가 생성되면 이전 뷰 상태가 있을 경우 복원되고 뷰의 Lifecycle이 CREATED로 바뀐다. 여기서 프래그먼트의 뷰와 관련된 모든 추가 상태를 복원해야 하고, onViewStateRestored()도 호출된다.

 

프래그먼트 및 뷰 STARTED

 

프래그먼트가 STARTED가 되면 onStart()가 호출된다.

 

프래그먼트 및 뷰 RESUMED

 

프래그먼트가 표시되면 모든 Animator 효과와 Transition 효과가 완료되서 프래그먼트를 상호작용에 사용할 수 있다.

이 상태로 전환되면 프래그먼트와 상호작용할 수 있으며, RESUMED가 아닌 프래그먼트는 뷰에 포커스를 수동 설정하거나 입력 메서드 공개 상태를 처리하려고 해선 안 된다.

 

하향 상태 전환 - 프래그먼트 및 뷰 STARTED

 

유저가 프래그먼트를 벗어나기 시작할 때도 아직 프래그먼트가 표시된 상태라면 프래그먼트와 관련 뷰의 Lifecycle은 STARTED로 전환되고, 프래그먼트는 onPause()를 호출한다.

 

프래그먼트 및 뷰 CREATED

 

프래그먼트가 더 이상 표시되지 않으면 프래그먼트, 관련 뷰의 Lifecycle은 CREATED로 전환된다.

이 전환은 중지 중인 상위 액티비티 or 프래그먼트에 트리거되고, 상위 액티비티 or 프래그먼트의 상태 저장에 의해서도 트리거된다.

onStop()과 onSaveInstanceState() 호출 순서는 API 28을 기준으로 달라진다. API 28 이전에선 onSaveInstanceState()가 onStop() 이전에 호출되지만, 28 이상에선 반대가 된다.

 

 

프래그먼트 CREATED, 뷰 DESTROYED

 

나가기 애니메이션, 전환이 모두 끝나고 프래그먼트의 뷰가 창에서 분리되면 프래그먼트의 뷰 Lifecycle이 DESTROYED로 전환되고 프래그먼트는 onDestroyView()를 호출한다.

이 때 프래그먼트 뷰는 생명주기의 끝에 도달했고 getViewLifecycleOwnerLivedata()는 null을 리턴한다. 이 때 프래그먼트 뷰의 모든 참조를 삭제해야 프래그먼트의 뷰에서 가비지 컬렉터가 가능하다.

 

프래그먼트 DESTROYED

 

프래그먼트가 삭제되거나 FragmentManager가 소멸되면 프래그먼트의 Lifecycle이 DESTROYED로 바뀌고 프래그먼트는 onDestroy()를 호출한다.

이 시점에서 프래그먼트는 생명주기의 끝에 도달한 상태다.

 

각 단계별 ON_START, ON_PAUSE 같은 이벤트를 관찰자에 전송하는 부분도 있는데 그 부분까지 포함하면 글 내용이 너무 길어질 것 같아 생략했다. 아래 링크를 참고하면 된다.

 

https://developer.android.com/topic/libraries/architecture/lifecycle?hl=ko

 

수명 주기 인식 구성요소로 수명 주기 처리  |  Android 개발자  |  Android Developers

새 Lifecycle 클래스를 사용하여 활동 및 프래그먼트 수명 주기를 관리합니다.

developer.android.com

 

반응형
Comments