coroutine에 해당하는 처리를 해주려면 코루틴 스코프를 열어줘야한다. fragment에서는 lifecycleScope를 자주 썼는데, viewLifecycleOwner의 lifecycleScope도 있다는 걸 이번에 알게되어 어떤 차이점이 있는 지 비교해보겠다.
# `lifecycleScope`
public val LifecycleOwner.lifecycleScope: LifecycleCoroutineScope
get() = lifecycle.coroutineScope
lifecycleScope는 Fragment 자체 생명주기랑 직결되어있다. 즉 `onAttach` -> `onDetach`에 해당하는 생명주기가 lifecycleScope다.
Fragment의 생명주기를 따르기 때문에 view 생명주기랑은 약간의 차이가 있다. fragment에서 binding을 해제하는 걸 생각해보자.
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
view 생명주기랑 차이나서 메모리 누수 날 위험을 없애기 위해 onDestroryView 때 binding에 null을 넣어준다.
# `viewLifecycleOwner.lifecycleScope`
`lifecycleScope`는 이전과 동일한 객체를 사용하지만 `LifecycleOwner`를 뷰로 지정해서 사용하는 방식이다. 즉 코루틴 스코프의 생명 주기를 `onCreateView` -> `onDestroyView`로 한정하는 것이다. 그래서 ui 작업이면 lifecycle을 view로 한정짓고, ui에 종속된 작업이 아니면 fragment 생명주기를 따르게 하는 게 좋다. io작업은 화면 회전과 같은 view 생명주기가 초기화되는 시점에도 유지되어야하니 작업 형태에 따라 조절해야된다.
직접 코드로 비교를 해보겠다.
viewLifecycleOwner.lifecycleScope.launch {
viewModel.data.collect { newData ->
updateUI(newData)
}
}
lifecycleScope.launch {
while(isActive) {
refreshData() // 백그라운드 작업, 네트워크 작업 등
}
}
ViewModel로 분리하면서 작업이 ViewModel의 생명주기를 따른다면 크게 신경 쓸건 아니지만, 최적화할 수 있는 부분은 최적화 하고 넘어가는게 좋을 것 같다. view update에 사용할 작업은 viewLifecycleOwner를 명시해주자.
한가지 주의할 점이라면 viewLifecycleOwner가 사용할 수 있는 시점이 onCreateView 이후라는 것이다. onCreate에서 접근하면 예외가 발생해서 runtime 에어로 앱이 죽는다. 그렇다고 onCreate에서 그냥 lifecycleScope로 ui에 접근하는 것도 말이 안된다는 건 알고 있을 것이다.
class TestFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
while(isActive) {
delay(1000)
updateUI() // View가 아직 생성되지 않았는데 UI 업데이트 시도하는 중
}
}
}
private fun updateUI() {
binding.tv.text = "Updated"
}
}
이렇게 하는 걸 지양해야된다.
도움이 됐다면 댓글이나 공감 버튼 한 번씩 누르고 가주세요!
'Android 🖥️ > 삽질⛏️' 카테고리의 다른 글
MLKit 활용하기 - FaceMeshDetection (0) | 2024.08.26 |
---|---|
Paging3 라이브러리 사용하기 (0) | 2024.07.30 |
RecyclerView에서 당기는 행동 처리 - edgeEffectFactory (0) | 2024.07.24 |
ViewType을 나눠 RecyclerView를 구성하기(feat. SealedClass) (0) | 2024.07.23 |
Expandable FAB(Floating Action Button) 구현하기 - ListPopupWindow (0) | 2024.07.20 |