본 내용은 학습을 위해 Comparing StateFlow, SharedFlow, and CallbackFlow 을 보고 입맛대로 정리한 글입니다.
val stateFlow = MutableStateFlow(0)
fun emitStateData(value : Int) {
CoroutineScope(Dispatchers.IO).launch {
println("emitted $value")
stateFlow.emit(value)
}
}
fun collectStateData() = CoroutineScope(Dispatchers.Default).launch {
stateFlow.collect {
println("collected $it")
}
}
val sharedFlow = MutableSharedFlow<Int>()
fun emitSharedData(value : Int) {
CoroutineScope(Dispatchers.IO).launch {
println("emitted $value")
sharedFlow.emit(value)
}
}
fun collectSharedData() = CoroutineScope(Dispatchers.Default).launch {
sharedFlow.collect {
println("collected $it")
}
}
var sendData: (data: Int) -> Unit = { }
var closeChannel: () -> Unit = { }
val callbackFlow = callbackFlow {
sendData = { data ->
println("callback send $data")
trySend(data)
}
closeChannel = { close() }
awaitClose {
sendData = {}
closeChannel = {}
println("Close CallbackFlow")
}
}
fun collectCallbackData() = CoroutineScope(Dispatchers.Default).launch {
callbackFlow.collect {
println("callback collect $it")
}
}
이해를 돕기 위해, 이후 모든 예제 코드 중
delay
를 개행(줄바꿈)으로 대체
fun main(): Unit = runBlocking {
println("Emit 1 before collect")
emitStateData(1)
println("Collect started")
val job1 = collectStateData()
}
출력 결과
Emit 1 before collect
emitted 1
Collect started
collected 1
fun main(): Unit = runBlocking {
println("Emit 1 before collect")
emitSharedData(1)
println("Collect started")
val job1 = collectSharedData()
}
출력 결과
Emit 1 before collect
emitted 1
Collect started
fun main(): Unit = runBlocking {
println("Emit 1 before collect")
sendData(1)
println("Collect started")
val job1 = collectCallbackData()
}
출력 결과
Emit 1 before collect
Collect started
fun main(): Unit = runBlocking {
println("Collect started")
val job1 = collectStateData()
println("Emit 2 after collect")
emitStateData(2)
println("Emit same value 2 again")
emitStateData(2)
}
출력 결과
Collect started
collected 0
Emit 2 after collect
emitted 2
collected 2
Emit same value 2 again
emitted 2
// SharedFlow
fun main(): Unit = runBlocking {
println("Collect started")
val job1 = collectSharedData()
println("Emit 2 after collect")
emitSharedData(2)
println("Emit same value 2 again")
emitSharedData(2)
}
// CallbackFlow
fun main(): Unit = runBlocking {
println("Collect started")
val job1 = collectCallbackData()
println("Emit 2 after collect")
sendData(2)
println("Emit same value 2 again")
sendData(2)
}
출력 결과
Collect started
Emit 2 after collect
emitted 2
collected 2
Emit same value 2 again
emitted 2
collected 2
fun main(): Unit = runBlocking {
println("Collect started")
val job1 = collectStateData()
println("Emit a new value 3")
emitStateData(3)
println("Collect again")
val job2 = collectStateData()
println("Emit 3 after collect again")
emitStateData(3)
}
출력 결과
Collect started
collected 0
Emit a new value 3
emitted 3
collected 3
Collect again
collected 3
Emit 3 after collect again
emitted 3
fun main(): Unit = runBlocking {
println("Collect started")
val job1 = collectStateData()
println("Emit a new value 3")
emitStateData(3)
println("Collect again")
val job2 = collectStateData()
println("Emit 4 after collect again")
emitStateData(4)
}
출력 결과
Collect started
collected 0
Emit a new value 3
emitted 3
collected 3
Collect again
collected 3
Emit 4 after collect again
emitted 4
collected 4
collected 4
fun main(): Unit = runBlocking {
println("Collect started")
val job1 = collectSharedData()
println("Emit a new value 3")
emitSharedData(3)
println("Collect again")
val job2 = collectSharedData()
println("Emit 3 after collect again")
emitSharedData(3)
}
출력 결과
Collect started
Emit a new value 3
emitted 3
collected 3
Collect again
Emit 3 after collect again
emitted 3
collected 3
collected 3
fun main(): Unit = runBlocking {
println("Collect started")
val job1 = collectCallbackData()
println("Emit a new value 3")
sendData(3)
println("Collect again")
val job2 = collectCallbackData()
println("Emit 3 after collect again")
sendData(3)
}
출력 결과
Collect started
Emit a new value 3
callback send 3
callback collect 3
Collect again
Emit 3 after collect again
callback send 3
callback collect 3
// StateFlow
fun main(): Unit = runBlocking {
println("Collect started")
val job1 = collectStateData()
println("Collect again")
val job2 = collectStateData()
println("Emit 4 after collect again")
emitStateData(4)
job1.cancel()
println("Cancel Job 1")
println("Emit 5 after cancel job1")
emitStateData(5)
job2.cancel()
println("Cancel Job 2")
println("Emit 6 after cancel job1")
emitStateData(6)
}
//SharedFlow
fun main(): Unit = runBlocking {
println("Collect started")
val job1 = collectSharedData()
println("Collect again")
val job2 = collectSharedData()
println("Emit 4 after collect again")
emitSharedData(4)
job1.cancel()
println("Cancel Job 1")
println("Emit 5 after cancel job1")
emitSharedData(5)
job2.cancel()
println("Cancel Job 2")
println("Emit 6 after cancel job2")
emitSharedData(6)
}
출력 결과
Collect started
collected 0 <-- StateFlow
Collect again
collected 0 <-- StateFlow
Emit 4 after collect again
emitted 4
collected 4
collected 4
Cancel Job 1
Emit 5 after cancel job1
emitted 5
collected 5
Cancel Job 2
Emit 6 after cancel job2
emitted 6
fun main(): Unit = runBlocking {
println("Collect started")
val job1 = collectCallbackData()
println("Collect again")
val job2 = collectCallbackData()
println("Emit 4 after collect again")
sendData(4)
println("Cancel Job 1")
job1.cancel()
println("Emit 5 after cancel job1")
sendData(5)
job2.cancel()
println("Cancel Job 2")
println("Emit 6 after cancel job2")
sendData(6)
println("Close Channel")
closeChannel()
}
출력 결과
Collect started
Collect again
Emit 4 after collect again
callback send 4
callback collect 4
Cancel Job 1
Close CallbackFlow
Emit 5 after cancel job1
Close CallbackFlow
Cancel Job 2
Emit 6 after cancel job2
Close Channel
awaitClose {...}
만 호출됨 (빨간색 사각형)close()
를 호출하여 채널을 닫으면, 두 코루틴에 awaitClose {...}
가 실행됨 (빨간색 사각형)closeChannel
를 사용하여 취소를 수행하면, 모든 것이 자동으로 취소되고 awaitClose {...}
를 호출함close()
를 직접 호출하여 callbackFlow 람다 내에서 자체 취소를 수행할 수 있음
아주 좋은 비교 글 감사합니다!!!