우리는 과거 뷰 시스템을 활용할 때 화면별 생명주기에 따라 코드를 실행하고 싶은 경우 onStart, onResume 같은 함수를 override 하여 코드를 구현하였다.
만약 코드가 코루틴 기반 구현인 경우 LifecycleOwner.lifecycleScope.launch 를 실행하고 내부적으로 repeatOnlifecycle 을 통해 각 화면 생명주기별 코드를 실행시키도 하였다.
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.someDataFlow.collect { data ->
// UI 업데이트
}
}
}
}
}
하지만 Compose 는 생명주기가 Activity, Fragment 와 같은 전통적인 방식과는 다르다.
Composition Start, Recompostion, Composition leave 3가지만 동작할 뿐이다.
그런데 만약 Composable 함수 내에서 Activity 생명주기에 맞춰 작업해야하는 내용이 있다면 어떻게 실행하겠는가?
이에 대비하여 사용되는 것이 Lifecycle 관련 Effect 들이다.
이 Effect 로는 LifecycleStartEffect 와 LifecycleResumeEffect 가 존재한다.
@Composable
fun LifecycleEffectTest() {
LifecycleStartEffect(true) {
Timber.d("OnStart")
onStopOrDispose { Timber.d("OnStop Or Dispose") }
}
LifecycleResumeEffect(true) {
Timber.d("OnResume")
onPauseOrDispose { Timber.d("OnPause Or Dispose") }
}
}
이것들은 Activity, Fragment 의 생명주기가 Start, Resume 인 경우 내부 코드를 실행 시키며 Stop, Pause 거나 Composition leave 되는 경우 onStopOrDispose, onPauseOrDispose 를 실행한다.
내부적으로 Lambda return 으로 인해, onStop, onPause 람다를 호출하도록 만들기 때문에 onStop, onPause 람다에 대한 코드 구현은 강제된다.
이제 한 번 코드를 실행해보자.

앱을 실행하면 Activity 가 onCreate -> onStart -> onResume 을 타므로 정상적으로 로그가 표시되었다.
이제 앱을 잠시 보이지 않게 백그라운드로 보내버리고, 다시 띄워보자.

액티비티의 생명주기대로 로그가 잘 찍히는 것을 확인할 수 있다.
메모리 누수 발생 위험이 존재하는 참조가 존재하는 경우 이를 생명주기에 맞춰 해지하거나, 생명주기에 종속된 특정한 코드를 실행하기 위해 사용된다.
key 가 존재하는 만큼 key 가 변경되면 내부 CoroutineScope 는 새롭게 실행된다.
LifecycleStartEffect, LifecycleStopEffect 이 두가지는 대칭되면 State 실행시의 코드 구현이 강제된다.
하지만 하나의 State 에서만 코드를 실행시키고 싶은 경우가 존재할 것이다.
이럴 때는 LifecycleEventEffect 를 사용하면 된다.
@Composable
fun LifecycleEffectTest() {
LifecycleEventEffect(Lifecycle.Event.ON_CREATE) {
Timber.d("ON_CREATE 실행")
}
LifecycleEventEffect(Lifecycle.Event.ON_START) {
Timber.d("ON_START 실행")
}
LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
Timber.d("ON_RESUME 실행")
}
LifecycleEventEffect(Lifecycle.Event.ON_PAUSE) {
Timber.d("ON_PAUSE 실행")
}
LifecycleEventEffect(Lifecycle.Event.ON_STOP) {
Timber.d("ON_STOP 실행")
}
}
Composition 은 액티비티가 파괴되기 전에 제거가 되므로, ON_DESTROY 때는 LifecycleEventEffect 가 실행이 불가능해진다.
이로 인해 내부적으로 에러를 뱉어 앱이 종료된다.