Android

Android Fragment Life Cycle

빨주노초잠만보 2023. 12. 26. 13:03

[안드로이드 공식 문서]

 

프래그먼트  |  Android 개발자  |  Android Developers

A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section

developer.android.com

🎉 Fragment

프래그먼트는 액티비티 처럼 화면을 구성하는 뷰입니다. 액티비티에 작성할 수 있는 모든 코드를 프래그먼트에 사용할 수 있단 뜻입니다 ! 하지만 프래그먼트 단독으로는 사용할 수 없기 때문에 항상 액티비티 내에서 호스팅 되야 하며 액티비티 라이프 사이클에 직접적인 영향을 받습니다.

 

🤔그럼 액티비티를 놔두고 굳이 프래그먼트를 사용하는 이유가 뭘까요? 

프래그먼트를 처음 도입한건 Android 3.0(API Lv 11) 부터였습니다. 프래그먼트는 테블릿이나 큰 화면에서 동작할 수 있는 앱을 개발하기 위해 제공되었습니다. 하나의 화면은 하나의 액티비티에서 만들어져야 하는데 화면이 크면 하나의 액티비티 클래스에 너무 많은 코드를 작성한다는 문제가 있었기 때문이죠.

 

아래 그림은 왼쪽에 목록을 보여주는 프래그먼트와 그 목록에서 항목을 선택하면 오른쪽에 상세 내용을 출력되는 예 입니다. 이 모든 내용을 Activity 하나에 모두 담긴 부담스럽겠죠? 그래서 두 화면을 각각 분리해서 작성하면 좀 더 유지보수 측면에서 유연성이 생길 수 있습니다. 

🎉 Fagment Life Cycle

Activity Life Cycle과 비교했을 때 추가된 몇가지 콜백 함수를 확인할 수 있습니다.  생성 프로세스에서는 onCreateView(), onViewCreated(), onViewStateRestored() 함수가 있고 종료 프로세스에선 onDestroyView() 가 추가 됐습니다.

 

View Life Cycle 관점에서 Fragment Life Cycle을 단계로 나눠 살펴보겠습니다.

  • 초기화(initalized) :  onAttach(), onCreate()에서 아직 View를 사용할 수 없으므로 View와 관련 없는 프래그먼트의 초기화 로직을 수행합니다. 
  • 생성(created) : onCreateView, onViewCreated()에서 Fragment 화면을 구성할 View를 준비합니다. onCreateView() 함수의 파라미터로 LayoutInflater 객체가 전달되므로 대부분 onCreateView 함수에서 Fragment 화면을 구성할 View 객체를 준비합니다.
 

Android LayoutInflater

제가 안드로이드를 처음 시작했을 때는 용어를 이해하는게 제일 힘들었습니다. Context, Activity, Intent, Coroutine 등등... 처음엔 저도 뭐가 뭔지도 모르고 그냥 막 했던 기억이 나네요... 곧 있을 면접

chanho-study.tistory.com

  • 시작(started) : Fragment가 사용자에게 보여집니다.
  • 재개(resumed) : 포커스를 가지고 사용자의 이벤트를 처리할 수 있습니다.
  • 소멸(destoryed) : 벡 스택(Back Stack : Fragment가 화면에 보이지 않는 순간 제거하지 않고 저장했다 다시 이용)의 사용 여부에 따라 생명 주기가 다르게 동작합니다. 
Back Stack 사용 : onPause() -> onStop()  -> onDestroyView -> 사용자가 화면을 다시킴 -> onCreateView() -> onViewCreated() -> onStart() -> onResume()
Back Stack 미사용 : onPause() -> onStop()  -> onDestroyView -> onDestory -> onDetach

 

🎉 Fagment Life Cycle Callback Method

onAttach

Fragment가 FragmentManager에 추가 되고 Host Activity에 연결될 때 호출되며 이 시점에 Fragment가 활성화 되고 FragmentManager가 Fragment의 생명주기를 관리합니다.

override fun onAttach(context: Context) {
    super.onAttach(context)
}

 

onCreate

Fragment만 생성되고 이 시점엔 아직 Fragment View가 생성되지 않기 때문에 Fragment의 View와 관련된 작업을 수행해선 안됩니다. onCreate 콜백 시점엔 savedInstanceState 파라미터를 전달받는데 이는 onSaveInstanceState() 콜백 함수에 의해 저장된 Bundle 값입니다. 

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
}

 

onCreateView

Fragment가 View를 그리기 위한 작업 즉 Layout을 inflate 하는 작업을 수행하고 따라서 반환 값도 View가 됩니다. 아래 예시는 Fragment에서 ViewBinding을 하는 예시입니다. return 값으로 이 Fragment Layout XML FILE의 가장 최상위 요소 즉, Fragment를 반환합니다.

class HomeFragment : Fragment() {
    private var _binding: FragmentHomeBinding ?= null
    private val binding get() = _binding!!

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentHomeBinding.inflate(inflater, container, false)

        return binding.root
    }
}

 

onViewCreated

onCreateView에서 반환된 View 객체를 파라미터로 전달받습니다. 이 시점 부터는 Fragment View의 LifeCycle이 Initialized 상태로 변하기 때문에 View의 초기값을 설정하거나 Live Data Observing, Adapter 초기화 등의 작업을 이곳에서 작업하는 것이 적절합니다.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
}

 

onStart

Fragment 가 사용자에게 보여질 수 있을 때 호출됩니다. 이 시점부터 Fragment의 child FragmentManager 통해 FragmentTransaction 을 안전하게 수행할 수 있습니다.

override fun onStart() {
    super.onStart()
}

 

onResume

사용자와 상호 작용하고 각종 이벤트를 처리할 수 있습니다.

override fun onResume() {
    super.onResume()
}

 

onPause

사용자가 Fragment를 떠나기 시작했지만 Fragment는 여전히 보이는 상태입니다. 

override fun onPause() {
    super.onPause()
}

 

onStop

Fragment가 더이상 화면에 보이지 않으면 Fragment와 View의 LifeCycle은 CREATED 상태가 됩니다. 이 상태는 Fragment의 Parent Activity나 Fragment가 중단됐을 때 뿐만 아니라 Parent Activity나 Fragment의 상태가 저장될 때도 호출됩니다.

 

API 28 버전을 기점으로 onSaveInstance() 함수와 onStop() 함수의 호출 순서가 달라졌는데 onStop() 이 onSaveInstanceState() 함수보다 먼저 호출됨으로써 onStop() 이 FragmentTransaction 을 안전하게 수행할 수 있는 마지막 지점이 되었습니다.

override fun onStop() {
    super.onStop()
}

 

onDestoryView()

Fragment가 화면에서 완전히 벗어났을 경우 Fragment와 연결된 View가 제거 중 일 때 호출되며 가비지 컬렉터에 의해 수거될 수 있도록 Fragment View에 대한 모든 참조가 제거되어야 합니다.

override fun onDestroyView() {
    super.onDestroyView()
}

 

onDestroy()

Fragment 가 제거되거나 FragmentManager 가 destroy 됐을 경우, 프래그먼트의 Lifecycle 은 DESTROYED 상태가 되고 Fragment Lifecycle 의 끝을 알립니다. 또한 메모리 누수 방지를 위해 바인딩했던 리소스를 해제하였습니다.

override fun onDestroy() {
    super.onDestroy()
    _binding = null
}