Suspend 함수는 단일 값을 비동기적으로 반환합니다.
그렇다면 비동기적으로 계산된 여러 값을 어떻게 반환할 수 있습니까? 여기에서 Kotlin의 흐름이 작용합니다.
여러 값 표현
Kotlin의 여러 값 컬렉션예를 들어 3개의 숫자로 표현할 수 있습니다.
목록누가 돌아오나 간단히 기능으로 모든모두 출력하시면 됩니다
fun simple(): List<Int> = listOf(1, 2, 3)
fun main() {
simple().forEach { value -> println(value) }
}
완전한 코드는 여기에서 찾을 수 있습니다
이 코드의 출력은 다음과 같습니다.
1
2
3
시퀀스
CPU 리소스를 사용하는 동안 차단된 코드 *1(각 작업에 100ms 소요)이 있는 숫자로 계산을 수행하면, 시리즈숫자를 나타내는 데 사용할 수 있습니다.
fun simple(): Sequence<Int> = sequence { // sequence builder
for (i in 1..3) {
Thread.sleep(100) // pretend we are computing it
yield(i) // yield next value
}
}
fun main() {
simple().forEach { value -> println(value) }
}
완전한 코드는 여기에서 찾을 수 있습니다
이 코드의 결과는 위와 동일하지만 각 숫자를 인쇄하기 전에 100ms를 기다립니다.
정지 기능
그러나 이러한 작업은 코드를 실행하는 기본 스레드를 차단합니다.
이러한 값이 비동기 코드로 계산되면 스레드를 차단하지 않고 계산하고 결과를 목록으로 반환합니다.
간단히 기능 폭로하다 수식어로 표시할 수 있습니다.
suspend fun simple(): List<Int> {
delay(1000) // pretend we are doing something asynchronous here
return listOf(1, 2, 3)
}
fun main() = runBlocking<Unit> {
simple().forEach { value -> println(value) }
}
완전한 코드는 여기에서 찾을 수 있습니다
이 코드는 1초를 기다린 다음 숫자를 인쇄합니다.
흐름
계략이라면
Sequence를 사용하여 동기식으로 계산된 값을 나타내는 것처럼 Flow를 사용할 수 있습니다.
fun simple(): Flow<Int> = flow { // flow builder
for (i in 1..3) {
delay(100) // pretend we are doing something useful here
emit(i) // emit next value
}
}
fun main() = runBlocking<Unit> {
// Launch a concurrent coroutine to check if the main thread is blocked
launch {
for (k in 1..3) {
println("I'm not blocked $k")
delay(100)
}
}
// Collect the flow
simple().collect { value -> println(value) }
}
완전한 코드는 여기에서 찾을 수 있습니다
이 코드는 각 숫자를 인쇄하기 전에 메인 스레드를 차단하지 않고 100ms를 기다립니다.
그건 100ms마다 “나는 차단되지 않았습니다”를 인쇄합니다.
이는 메인 스레드에서 실행되는 별도의 코루틴에 의해 확인됩니다.
I'm not blocked 1
1
I'm not blocked 2
2
I'm not blocked 3
3
이전 예제의 코드 및 흐름다음과 같은 차이점이 있는지 확인해 보겠습니다.
- 흐름빌더 기능 흐름오전.
- 흐름 { … } 블록 내의 코드는 일시 중단될 수 있습니다.
- 간단히 기능이 더 이상 폭로하다 수정자로 표시되지 않았습니다.
- 방출하다 흐름의 값은 함수*2를 통해 출력됩니다.
- 모으다 함수를 사용하여 흐름에서 *3 값을 수집합니다.
간단히 기능 흐름 { … } 블록 내부 지연붓다 스레드 수면*4로 교체하는 경우 메인 스레드가 차단된 것을 볼 수 있습니다.
다음 내용은 독자의 이해를 돕기 위해 번역자가 추가한 내용입니다.
*하나. 작업이 오래 걸려 스레드가 차단된 경우를 나타냅니다.
*2. Reactive Programming의 출시를 의미합니다.
*삼. 리액티브 프로그래밍 구독.
*4. 이는 다음으로 변경됨을 의미합니다.
fun simple(): Flow<Int> = flow {
for (i in 1..3) {
Thread.sleep(100)
emit(i)
}
}
이 문서는 공식 코루틴 문서를 번역한 것입니다.
원본 텍스트의 최종 편집: 2022년 9월 28일
해류는 차갑다
흐름~이다 시리즈콜드 스트림 * 1과 비슷합니다.
흐름 빌더의 코드는 흐름가다 모으다작동할 때까지 실행되지 않습니다.
이는 다음 예제에서 명확해집니다.
fun simple(): Flow<Int> = flow {
println("Flow started")
for (i in 1..3) {
delay(100)
emit(i)
}
}
fun main() = runBlocking<Unit> {
println("Calling simple function...")
val flow = simple()
println("Calling collect...")
flow.collect { value -> println(value) }
println("Calling collect again...")
flow.collect { value -> println(value) }
}
완전한 코드는 여기에서 찾을 수 있습니다
결과는 다음과 같습니다.
Calling simple function...
Calling collect...
Flow started
1
2
3
Calling collect again...
Flow started
1
2
3
흐름을 반환 간단히 기능 폭로하다 이것이 수정자로 표시되지 않은 이유입니다.
간단한() 함수 호출 자체는 즉시 반환되며 아무 것도 기다리지 않습니다.
흐름은 모으다다시 시작할 때마다 모으다이것이 모든 호출에 “Flow started”가 표시되는 이유입니다.
다음 내용은 독자의 이해를 돕기 위해 번역자가 추가한 내용입니다.
*하나. Flow는 발급자 유형의 반응형 프로그래밍 중 Cold Stream에 속합니다.
콜드 스트림(Cold Stream)이라고도 하는 콜드 스트림(Cold Stream)은 구독이 발생할 때까지 블록 내부의 코드가 실행되지 않고 구독이 발생하면 블록 내부의 코드가 실행되는 스트림을 말합니다.
반대로 코드는 구독 없이 Hot Stream에서도 실행됩니다.
콜드 스트림과 핫 스트림을 구분하는 기준은 게시가 아니라 코드 실행이라는 점에 유의해야 합니다.
오전. 예를 들어 핫스트림인 StateFlow는 구독 후 즉시 게시된 값의 마지막 값을 게시하지만 코드를 실행하여 내보낸 값을 업데이트하지 않습니다.
이 문서는 공식 코루틴 문서를 번역한 것입니다.
원래의: 비동기식 흐름 – 흐름이 차갑습니다.
원본 텍스트의 최종 편집: 2022년 9월 28일