stateIn
으로 Flow
를 StateFlow
로 변환하는 것에 대한 간단한 이해를 정리한 글
Flow
는 cold 스트림
collect
가 호출되기 전까지는 아무런 동작 하지 않음collect
가 호출되면 처음부터 발행val myFlow = flow {
// collect가 호출되기 전까지
// 해당 코드는 실행되지 않음
// 0부터 100까지 1초 간격으로 값을 발행(emit)
repeat(100) {
Log.d(TAG, ">> emit -> $it")
emit(it)
delay(1000)
}
}
CoroutineScope(Dispatchers.Main).launch {
launch {
// 처음부터 collect 시작
myFlow.collect { Log.d(TAG, "#1st -> $it") }
}
delay(2000) // 다음 collect 호출까지 2초 대기
launch {
// 처음부터 collect 시작
myFlow.collect { Log.d(TAG, "#2nd -> $it") }
}
}
첫번째 collect
가 호출되면 0부터 값이 발행(emit)되기 시작한다.
2초 후 두번째 collect
가 호출되면 역시 0부터 값이 방출되기 시작한다.
StateFlow
는 hot 스트림
val myFlow = flow {
// collect가 호출되기 전까지
// 해당 코드는 실행되지 않음
// 0부터 100까지 1초 간격으로 값을 방출(emit)
repeat(100) {
Log.d(TAG, ">> emit -> $it")
emit(it)
delay(1000)
}
}
// Flow를 StateFlow로 변환
val myStateFlow = myFlow.stateIn(
scope = lifecycleScope,
started = SharingStarted.Lazily,
initialValue = -1
)
CoroutineScope(Dispatchers.Main).launch {
delay(1000) // 1초 대기
launch {
// 가장 최근에 방출된 값부터 collect된다. (= 1)
myStateFlow.collect { Log.d(TAG, "#1st -> $it") }
}
delay(2500) // 2.5초 대기
launch {
// 가장 최근에 방출된 값부터 collect된다. (= 3)
myStateFlow.collect { Log.d(TAG, "#2nd -> $it") }
}
}
myFlow
를 stateIn
을 통해 StateFlow
로 변환시킴으로서 myStateFlow
가 myFlow
를 collect하고 있는 것이라고 이해했다.
collect하는 곳이 있으니 myFlow
는 계속해서 값을 발행하게 되고, myStateFlow
는 그 값을 받아 가장 최신 값을 hold하고 있는다.
myStateFlow
에 대해 collect
가 호출되면 들고있던 최신 값을 발행한다.
로그는 다음과 같다.
>> emit -> 0
>> emit -> 1
#1st -> 1 // collect를 시작한 시점에서의 가장 최신 값
>> emit -> 2
#1st -> 2
>> emit -> 3
#1st -> 3
#2nd -> 3 // collect를 시작한 시점에서의 가장 최신 값
>> emit -> 4
#1st -> 4
#2nd -> 4
.
.
.
Flow에 stateIn을 사용해서 StateFlow로 만든다는게 어떤 의미인건지 잘 감이 안잡혔는데 계속 들여다보니 나름대로 정리할 수 있었다.