(Topic) 005. 코루틴 & 플로우 스터디 복기 3

1. LifecycleCoroutineScope

CoroutineScope는 Android의 Activity 혹은 Fragment의 생명주기와 Dispatchers.Main.immediate 상태와 연계되어 있다.

예를 들어 onDestroy 등으로 생명주기가 종료되거나 파괴되면 CoroutineScope도 취소되는 식이다.

CoroutineScope는 좀 더 특정한 상태에서 호출할 수 있는 launch 함수를 제공해주며, 그 목록은 아래와 같다.

  • launchWhenCreated
  • launchWhenStarted
  • launchWhenResumed

1.1. launchWhenCreated

1
fun launchWhenCreated(block: (@ExtensionFunctionType suspend CoroutineScope.() -> Unit)?): Job

launchWhenCreatedLifecycleCoroutineScope를 제어하는 LifeCycle이 현재 Lifecycle.State.CREATED 상태에 있을 때 실행할 수 있다.

1.2. launchWhenStarted

1
fun launchWhenResumed(block: (@ExtensionFunctionType suspend CoroutineScope.() -> Unit)?): Job

launchWhenResumedLifecycleCoroutineScope를 제어하는 LifeCycle이 현재 Lifecycle.State.RESUMED 상태에 있을 때 실행할 수 있다.

1.3. launchWhenStarted

1
fun launchWhenStarted(block: (@ExtensionFunctionType suspend CoroutineScope.() -> Unit)?): Job

launchWhenResumedLifecycleCoroutineScope를 제어하는 LifeCycle이 현재 Lifecycle.State.STARTED 상태에 있을 때 실행할 수 있다.

1.4. repeatOnLifecycle

1
2
3
4
5
6
7
8
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
// Do Somethings.
}
}
}

위의 세 함수들의 반환하는 JobLifeCycle이 파괴되면 취소된다.

또한 리소스의 낭비를 야기할 가능성이 있어 삭제 예정인 함수이므로, 주로 LifeCycle 객체의 repeatOnLifecycle 함수를 호출하는 것이 권장된다.

repeatOnLifecycle는 Android의 생명주기와 밀접한 관련이 있는 UI Layer에서 Flow를 수집하는 데 권장되는 방법이다.

인자로 넘겨받은 생명주기 단계에 따라 해당 단계에 맞는 새로운 코루틴을 자동으로 시작하며, 생명 주기가 초기화되는 onCreate에서 호출하는 것이 가장 좋은 방법이다.

보통 리소스의 낭비가 발생하는 것은 Activity등이 백그라운드 상태임에도 불구하고 계속해서 Flow를 통해 데이터를 송신하고 수신하는 경우인데, repeatOnLifecycle를 사용하면 백그라운드 상태에서 일시 정지시킬 수 있다.

2. Flow의 shareIn 과 stateIn

2.1. shareIn

1
fun <T> Flow<T>.shareIn(scope: CoroutineScope, started: SharingStarted, replay: Int = 0): SharedFlow<T>

shareIn을 사용하면 콜드 플로우를 핫 플로우로 만들 수 있다.

이 연산자는 생성 혹은 유지 비용이 많이 드는 콜드 플로우가 있는 상태에서 여러 구독자가 존재하는 경우 유용하다.

  • scope: CoroutineScope : 코루틴을 실행할 scope
  • started: SharingStarted : 코루틴의 시작 및 중지를 위한 값
  • replay: Int : 새로운 구독자에게 지정된 수만큼 값을 반복

2.2. stateIn

1
fun <T> Flow<T>.stateIn(scope: CoroutineScope, started: SharingStarted, initialValue: T): StateFlow<T>

stateIn을 사용하면 플로우를 StateFlow로 만들 수 있다.

기존 플로우에 대해서 MutableStateFlow를 생성하고 넘겨주는 것보다 보다 간편하게 넘겨줄 수 있다는 장점이 있다.

  • scope: CoroutineScope : 코루틴을 실행할 scope
  • started: SharingStarted : 코루틴의 시작 및 중지를 위한 값
  • initialValue: T : StateFlow의 초기값

References