// code 1
interface Flow<out T> {
suspend fun collect(collecotr: FlowCollector<T>)
}
interface FlowCollector<in T> {
suspend fun emit(value: T)
}
// code 3
flow {
emit(1)
emit(2)
}
// 1
.collect {
println(it)
}
// 2
// code 4
public fun <T> flow(@BuilderInference block: suspend FlowCollector<T>.() -> Unit): Flow<T> = SafeFlow(block)
// Named anonymous object
private class SafeFlow<T>(private val block: suspend FlowCollector<T>.() -> Unit) : AbstractFlow<T>() {
override suspend fun collectSafely(collector: FlowCollector<T>) {
collector.block()
}
}
- flow를 이해하기 어려운 이유는 람다와 sam 구조로 인한 생략 때문(내 개인적 느낌)
- code 3과 code 4를 보면 주석1까지는 SafeFlow클래스를 생성한것임
- SafeFlow는 Flow의 구현체임
- flow의 액션람다는 FlowCollector리시버
- 주석2에서 SafeFlow의 collect함수를 호출함
- 그러면, collectSafely 함수가 호출됨
- collectSafely 내부에서는 collector.block이 호출되고 있으니까 1번의 flow의 액션 람다가 호출되는 것임
- 액션람다에서는 (눈을 크게뜨면) FlowCollector.emit을 호출하고있는 것임
- FlowCollector.emit함수의 실제 본문은 2번 액션람다임
- 즉 println이 호출 됨
- 그래서 println 1, println 2가 차례로 호출됨
'개발 > 코틀린' 카테고리의 다른 글
코틀린 코루틴 내부 동작 이해하기 (0) | 2023.12.28 |
---|---|
변성 - 공변, 무공변, 반공변 (0) | 2020.11.22 |