LifecycleScope
안드로이드의 생명주기를 인식하는 코루틴 스코프이다.
lifecycleScope.launch {
}
액티비티 혹은 프래그먼트에서 일반적인 코루틴을 만들어 사용을 하는 경우 LifecycleOwner
가 Destroyed
될 때 실행 중인 코루틴을 취소하기 위해서는 CoroutineContext.cancel()
을 호출해야 한다.
하지만 LifecycleScope
에서 실행되는 코루틴은 생명주기에 맞춰 안전하게 종료하며 하위 코루틴의 작업들을 모두 취소한다.
internal class LifecycleCoroutineScopeImpl(
override val lifecycle: Lifecycle,
override val coroutineContext: CoroutineContext
) : LifecycleCoroutineScope(), LifecycleEventObserver {
init {
// in case we are initialized on a non-main thread, make a best effort check before
// we return the scope. This is not sync but if developer is launching on a non-main
// dispatcher, they cannot be 100% sure anyways.
if (lifecycle.currentState == Lifecycle.State.DESTROYED) {
coroutineContext.cancel()
}
}
fun register() {
launch(Dispatchers.Main.immediate) {
if (lifecycle.currentState >= Lifecycle.State.INITIALIZED) {
lifecycle.addObserver(this@LifecycleCoroutineScopeImpl)
} else {
coroutineContext.cancel()
}
}
}
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (lifecycle.currentState <= Lifecycle.State.DESTROYED) {
lifecycle.removeObserver(this)
coroutineContext.cancel()
}
}
}
ViewModelScope
안드로이드 생명주기를 인식하는 코루틴 스코프로, ViewModel
에서 onCleared()
호출 시 모든 코루틴이 취소된다.
class MainViewModel: ViewModel() {
init {
viewModelScope.launch {
}
}
}
launchWhen···()
생명주기의 상태에 맞춰 코루틴을 실행, 중단, 재개하고 싶은 경우에는 launchWhenCreated
, launchWhenStarted
, launchWhenResumed
함수를 사용하면 된다.
When
이후 접미어에 해당하는 생명주기에 맞춰 실행이 되고, 생명주기의 상태가 맞지 않는다면 정지가 되고, 다시 생명주기 상태가 충족되면 재개한다.
lifecycleScope.launchWhenStarted {
}
repeatOnLifeCycle
생명주기의 상태에 맞춰 코루틴을 시작, 취소, 재시작하고 싶은 경우에는 LifecycleOwner
의 확장 함수인 repeatOnLifeCycle
을 사용하면 된다.
Flow
를 launchWhen···()
내에서 사용하게 되면 onDestroy()
에서 collect
가 중단되기 때문에 백그라운드 상태로 들어가게 되면 생명주기의 상태가 onStop()
이 되기 때문에 collect
가 중단되지 않는다.
하지만 repeatOnLifeCycle
을 사용하면 포그라운드 상태일 때만 한정지어 특정 생명주기가 트리거 되었을 때 코루틴 Job
을 생성한다.
백그라운드 상태로 들어가게 되면 onStop()
에서 Job
이 취소되고, 다시 생명주기 상태가 충족되면 처음부터 다시 작업을 시작하기 때문에 백그라운드 상태에서 collect
를 중단할 수 있게 된다.
lifeCycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
}
}