프래그먼트를 사용하면 화면하나를, 독립적으로 작동하는 부분화면 여러개로 구현할 수 있다
프레그먼트는 엑티비티처럼 레이아웃을 표시하고, 생명주기를 가지며 입력 이벤트를 받을 수 있다
하지만 독립적으로는 존재할 수 없고, 해당 프래그먼트를 관리하는 호스트 액티비티나 프래그먼트 하위에서만 존재할 수 있다
엑티비티는 안드로이드 4대 컴포넌트 중 하나로 안드로이드 시스템에서 관리하지만,
프레그먼트는 안드로이드 시스템이 직접 관리하지 않고 FragmentManager가 관리하기 때문에 엑티비티보다 메모리 리소스가 상대적으로 덜 소모된다.
또한 한번 작성된 프레그먼트는 여러 액티비티에서 재사용이 가능하며, 따라서 UI 구현에 필요한 작업량을 감소시킬 수 있다
# 프래그먼트 수명 주기 상태 및 콜백
-> 그림을 보면 Fragment Lifecycle 과 View Lifecycle이 상이한 것을 볼 수 있다.
Fragment의 Lifecycle이 변화되는 순간 Fragment Callback 함수를 호출하게 되고, 해당 콜백 함수가 종료되는 시점에 View의 Lifecycle 에 이벤트를 전달하게 된다
# onAttach() & onCreate()
Fragment CREATED
onAttach()
프래그먼트가 호스트 액티비티에 attach 된다
onCreate()
프래그먼트 자체가 생성된다
-> CREATED 상태에 있을 때, 프래그먼트는 FragmentManager에 추가되며 onAttach()와 onCreate()가 차례대로 호출된다
onAttach()에서는 프래그먼트가 호스트 액티비티에 attach 되고, onAttach()에서 작업이 성공적으로 이루어지면 onCreate()에서 프래그먼트 자체가 생성된다. 이때 프래그먼트 뷰는 아직 생성되지 않은 상태이므로, 뷰와 관련된 작업을 onCreate() 내부에 하는 것은 적절하지 않다.
# onCreateView() & onViewCreated()
Fragment CREATED & View INITIALIZED
onCreateView()
프래그먼트 뷰가 초기화되며, 정상적으로 초기화가 되었다면 뷰 객체를 반환한다
onViewCreated()
onCreateView()에서 뷰 객체가 반환된 직후에 호출되며, 뷰가 완전히 생성되었음을 보장한다
-> onCreate() 이후에는 onCreateView() 와 onViewCreated() 콜백함수가 이어서 호출됩니다. onCreateView() 의 반환값으로 정상적인 Fragment View 객체를 제공했을 때만 Fragment View 의 Lifecycle 이 생성된다
이때 레이아웃을 inflate 하기 때문에 findViewById() 또는 View Binding을 사용해서 다른 뷰들을 참조할 수도 있지만, 종종 레이아웃이 제대로 초기화가 되지 않을 수도 있다. 그렇기때문에 뷰에 대한 참조 및 작업은 뷰가 완전히 생성된 이후인 onViewCreated()에서 하는 것이 더 안전하다
class MainFragment : Fragment(){
private lateinit var binding : FragmentMainBinding
private val viewModel : ViewModel by inject()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentMainBinding.inflate(inflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstance: Bundle?){
super.onViewCreated(view, savedIntanceState)
binding.btn.setOnClickListener {
...
}
viewModel.getAll().observe(viewLifecycleOwner, Observer{
...
})
}
}
# onViewStateRestored()
Fragment & View CREATED
onViewStateRestored()은 저장해둔 모든 state 값이 Fragment 의 View의 계층구조에 복원되었을 때 호출된다.
따라서 여기서부터는 체크박스 위젯이 현재 체크 되어있는지 등 각 뷰의 상태값을 체크할 수 있습니다.
# onStart()
Fragment & View STARTED
Fragment 가 사용자에게 보여질 수 있을 때 호출된다
childFragmentManager를 통해 FragmentTransaction을 안전하게 수행할 수 있다.
# onResume()
Fragment & View RESUMED
사용자와 프래그먼트가 상호작용 할 수 있는 상태로,
프래그먼트가 보이는 상태에서 모든 Animator와 Transition 효과가 종료된 후 호출된다.
# onPause()
Fragment & View STARTED
사용자가 프래그먼트를 떠났지만 기존 프래그먼트가 조금이라도 보일 때 호출된다.
(Fragment 는 여전히 visible 일 때 onPause()가 호출)
이 때 프래그먼트와 프래그먼트 뷰의 생명주기는 PAUSED가 아닌 STARTED 상태가 된다.
엄밀히 따지면 Lifecycle 에 PAUSE 와 STOP 에 해당하는 상태가 없는 상태다
# onStop()
Fragment & View CREATED
프래그먼트가 더이상 보이지 않을 때 호출된다.
onStop()은 호스트 액티비티나 프래그먼트가 중단되었을 뿐만 아니라, 부모 액티비티나 프래그먼트의 상태가 저장될 때도 호출된다
주의해야할 점이 있는데, API 레벨 28 이후 onSaveInstanceState()와 onStop() 호출 순서가 달라졌고, 따라서 onStop()이 FragmentTransaction을 안전하게 수행하는 마지막 지점이 되었다.
# onDestroyView()
Fragment CREATED & View DESTROYED
프래그먼트의 뷰가 소멸될 시 호출된다
이때 프래그먼트 자체는 아직 메모리에 남아있으므로, 프래그먼트 뷰에 대한 모든 참조를 제거해야 메모리 누수를 방지할 수 있다. 따라서 만약 View Binding을 사용하고 있다면 onDestroyView()에서 binding 변수를 null로 만들어 주는 것이 좋다
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
# onDestroy()
Fragment DESTROYED
프래그먼트 또는 프래그먼트 매니저가 소멸되었을 경우 호출되며,
onDestroy()가 호출되었다는 것은 프래그먼트의 생명주기도 종료되었다는 것을 의미한다.
# 참고한 공식문서와 자료
https://developer.android.com/guide/fragments/lifecycle?hl=ko
https://readystory.tistory.com/199
https://velog.io/@jeongminji4490/Android-Fragment-Lifecycle
'개발 노트 > Kotlin' 카테고리의 다른 글
[Android/Kotlin] 세로/가로 모드 ui 분리 구현 (1) | 2024.04.07 |
---|---|
[Android] Fragment간 데이터통신 방식 (0) | 2024.03.29 |
[Android] Activity Stack 및 backStack (0) | 2024.03.29 |
버튼 눌렀을때 Fragment화면 나타내기 (0) | 2024.03.28 |
코틀린의 ViewBinding과 DataBinding (0) | 2024.03.28 |