π 16.1 νλ‘μ°λ μ°μμ μΈ κ°μ μ€νΈλ¦Όμ λͺ¨λΈλ§νλ€
suspend fun createValues(): List<Int> {
return buildList {
add(1)
delay(1.seconds)
add(2)
delay(1.seconds)
add(3)
delay(1.seconds)
}
}
fun main() = runBlocking {
val list = createValues()
list.forEach {
log(it)
}
}
- λͺ¨λ κ°μ΄ κ³μ° λ ν ν¨μκ° κ°μ λ°νν¨.
- ν¨μκ° μ€νμ λ§μΉ λκΉμ§ κΈ°λ€λ¦¬μ§ μκ³ κ°μ μ¬μ©ν μ μλλ‘ λΉλκΈ°μ μΌλ‘ λ°ννκ³ μΆμ λ νλ‘±μ°κ° μ μ©νλ€.
- νλ‘μ°λ μκ°μ΄ μ§λ¨μ λ°λΌ λνλλ κ°κ³Ό μμ ν μ μκ² ν΄μ£Όλ μ½λ£¨ν΄ κΈ°λ°μ μΆμνλ€
π 16.1.1 νλ‘μ°λ₯Ό μ¬μ©νλ©΄ λ°°μΆλμλ§μ μμλ₯Ό μ²λ¦¬ν μ μλ€
fun createValues(): Flow<Int> {
return flow {
emit(1)
delay(1.seconds)
emit(2)
delay(1.seconds)
emit(3)
delay(1.seconds)
}
}
fun main() = runBlocking {
val myFlowOfValues = createValues()
myFlowOfValues.collect { log(it) }
}
0 [main @coroutine#1] 1
1036 [main @coroutine#1] 2
2042 [main @coroutine#1] 3
- μμκ° λ°°μΆλλ μ¦μ νμλλ€.
π 16.1.2 μ½νλ¦° νλ‘μ°μ μ¬λ¬ μ ν
- μ½λ νλ‘μ°
- λΉλκΈ° λ°μ΄ν° μ€νΈλ¦Ό
- κ°μ΄ μ€μ λ‘ μλΉλκΈ° μμν λλ§ κ°μ λ°°μΆ
- ν« νλ‘μ°
- λΈλ‘λμΊμ€νΈ λ°©μ
- κ°μ΄ μ€μ λ‘ μλΉλκ³ μλμ§μ μκ΄μμ΄ λ 립μ μΌλ‘ λ°°μΆ
π 16.2 μ½λ νλ‘μ°
π 16.2.1 flow λΉλ ν¨μλ₯Ό μ¬μ©ν΄ μ½λ νλ‘μ° μμ±
fun main() = runBlocking {
val letters = flow {
log("Emitting A!")
emit("A")
delay(200.milliseconds)
log("Emitting B!")
emit("B")
}
}
- μλ¬΄λ° μΆλ ₯λ λνλμ§ μλλ€.
flowλΉλ ν¨μλ₯Ό νΈμΆν΄λ μ€μ μμ μ΄ μμλμ§ μμ.
val counterFlow = flow {
var x = 0
while (true) {
emit(x++)
delay(200.milliseconds)
}
}
- μ΄ λ£¨νλ μ€μ λ‘ νλ‘μ°κ° μμ§λ λλ§ μ€ν
π 16.2.2 μ½λ νλ‘μ°λ μμ§λκΈ° μ κΉμ§ μμ μ μννμ§ μλλ€
Flowμ λν΄collectν¨μλ₯Ό νΈμΆνλ©΄ κ·Έ λ‘μ§μ΄ μ€νλλ€- νλ‘μ°λ₯Ό μμ§ν λλ νλ‘μ° λ΄λΆμ μΌμ μ€λ¨ μ½λλ₯Ό μ€ννλ―λ‘
collectλ μΌμ μ€λ¨ ν¨μμ΄λ©°, νλ‘μ°κ° λλ λκΉμ§ μΌμ μ€λ¨λλ€.
val letters = flow {
log("Emitting A!")
emit("A")
delay(200.milliseconds)
log("Emitting B!")
emit("B")
}
fun main() = runBlocking {
letters.collect {
log("Collecting: $it")
delay(500.milliseconds)
}
}
0 [main @coroutine#1] Emitting A!
15 [main @coroutine#1] Collecting: A
737 [main @coroutine#1] Emitting B!
737 [main @coroutine#1] Collecting: B
- μμ§μκ° νλ‘μ°μ λ‘μ§μ μ€ννλ μ± μμ΄ μλ€.
- μμ A, B μ¬μ΄μ μ§μ°μκ°μ 700λ°λ¦¬μ΄μ΄λ€.
- μμ§μκ° νλ‘μ° λΉλμ μ μλ λ‘μ§μ μ€νμ μ΄λ°ν΄μ 첫 λ²μ§Έ λ°°μΆ λ°μ
- μμ§μκ° μ°κ²°λ λλ€κ° νΈμΆλλ©΄μ λ©μμ§λ₯Ό κΈ°λ‘νκ³ 500λ°λ¦¬μ΄ λμ μ§μ°
- νλ‘μ° λλ€κ° κ³μ μ€νλλ©° 200λ°λ¦¬μ΄ λμ μΆκ° μ§μ°κ³Ό λ°°μΆμ΄ λ°μ
fun main() = runBlocking {
letters.collect {
log("(1) Collecting: $it")
delay(500.milliseconds)
}
letters.collect {
log("(2) Collecting: $it")
delay(500.milliseconds)
}
}
0 [main @coroutine#1] Emitting A!
16 [main @coroutine#1] (1) Collecting: A
743 [main @coroutine#1] Emitting B!
743 [main @coroutine#1] (1) Collecting: B
1247 [main @coroutine#1] Emitting A!
1247 [main @coroutine#1] (2) Collecting: A
1958 [main @coroutine#1] Emitting B!
1958 [main @coroutine#1] (2) Collecting: B
- κ°μ νλ‘μ°λ₯Ό μ¬λ¬ λ² μμ§ν μ μλ€.
π 16.2.3 νλ‘μ° μμ§ μ·¨μ
fun main() = runBlocking {
val collector = launch {
counterFlow.collect {
println(it)
}
}
delay(5.seconds)
collector.cancel()
}
- μμ§μμ μ½λ£¨ν΄μ μ·¨μνλ©΄ λ€μ μ·¨μ μ§μ μμ νλ‘μ°μ μμ§μ΄ μ€λ¨λλ€.
π 16.2.4 μ½λ νλ‘μ°μ λ΄λΆ ꡬν
- μ½νλ¦°μ μ½λ νλ‘μ°λ μΌμ μ€λ¨ ν¨μμ μμ κ°μ²΄ μ§μ λλ€λ₯Ό κ²°ν©ν λλν μ‘°ν©μ΄λ€.
- μ½λ νλ‘μ°μ μ μλ λ§€μ° κ°λ¨νλ€.
FlowμFlowCollectorλΌλ 2κ°μ§ μΈν°νμ΄μ€λ§ νμ
collectλ₯Ό νΈμΆνλ©΄ νλ‘μ° λΉλ ν¨μμ λ³Έλ¬Έμ΄ μ€ν- μ΄ μ½λκ°
emitμ νΈμΆνλ©΄emitμ μ λ¬λ νλΌλ―Έν°λ‘collectμ μ λ¬λ λλ€κ° νΈμΆ - λλ€ ννμμ΄ μ€νμ μλ£νλ©΄ ν¨μλ λΉλ ν¨μμ λ³Έλ¬ΈμΌλ‘ λμκ° κ³μ μ€ν
- μ½λ νλ‘μ°λ κ° μ€νΈλ¦Όμ μ²λ¦¬νλ κ°λ²Όμ°λ©΄μλ μμ£Ό μΈλͺ¨ μκ³ νμ₯μ± μλ μΆμνλ₯Ό μ 곡
π 16.2.5 μ±λ νλ‘μ°λ₯Ό μ¬μ©ν λμμ± νλ‘μ°
suspend fun getRandomNumber(): Int {
delay(500.milliseconds)
return Random.nextInt()
}
val randomNumbers = flow {
repeat(10) {
emit(getRandomNumber())
}
}
fun main() = runBlocking {
randomNumbers.collect {
log(it)
}
}
0 [main @coroutine#1] -1441864547
513 [main @coroutine#1] 1101626017
1020 [main @coroutine#1] 313359960
1527 [main @coroutine#1] -2002910241
2033 [main @coroutine#1] 890150628
2538 [main @coroutine#1] -1433970862
3045 [main @coroutine#1] 1503636281
3548 [main @coroutine#1] -1528949568
4055 [main @coroutine#1] -1562012272
4561 [main @coroutine#1] 2076525050
- νλ‘μ°λ μμ°¨μ μΌλ‘ μ€νλλ©°, λͺ¨λ κ³μ°μ λμΌ μ½λ£¨ν΄μμ μ€ν
val randomNumbers = channelFlow {
repeat(10) {
launch {
send(getRandomNumber())
}
}
}
- λμμ±μΌλ‘ νΈμΆν μ μλ νλ‘μ° λΉλ:
channelFlow - μ±λ νλ‘μ°λ λ΄λΆμ μΌλ‘ λ λ€λ₯Έ λμμ± κΈ°λ³Έ μμμΈ μ±λμ κ΄λ¦¬ν΄μΌ νκΈ° λλ¬Έμ μμ±νλ λ° μ½κ° λΉμ©μ΄ λ λ€.
- μ±λμ μ½λ£¨ν΄ κ° ν΅μ μ μν λΉκ΅μ μ μμ€μ μΆμν
- νλ‘μ° μμμ μλ‘μ΄ μ½λ£¨ν΄μ μμν΄μΌ νλ κ²½μ°μλ§ μ±λ νλ‘μ° μ ν
π 16.3 ν« νλ‘μ°
- ν« νλ‘μ°μμλ κ° μμ§μκ° νλ‘μ° λ‘μ§ μ€νμ λ
립μ μΌλ‘ μ΄λ°νλ λμ , μ¬λ¬ ꡬλ
μλΌκ³ λΆλ¦¬λ μμ§μλ€μ΄ λ°°μΆλ νλͺ©μ 곡μ νλ€.
- 곡μ νλ‘μ°: κ°μ λΈλ‘λμΊμ€νΈνκΈ° μν΄ μ¬μ©
- μν νλ‘μ°: μνλ₯Ό μ λ¬νλ νΉλ³ν κ²½μ°μ μ¬μ©
π 16.3.1 곡μ νλ‘μ°λ κ°μ ꡬλ μμκ² λΈλ‘λμΊμ€νΈνλ€
- 곡μ νλ‘μ°λ ꡬλ μκ° μ‘΄μ¬νλμ§ μ¬λΆμ μκ΄μμ΄ λ°°μΆμ΄ λ°μνλ λΈλ‘λμΊμ€νΈ λ°©μ
class RadioStation {
private val _messageFlow = MutableSharedFlow<Int>()
val messageFlow = _messageFlow.asSharedFlow()
fun beginBroadcasting(scope: CoroutineScope) {
scope.launch {
while (true) {
delay(500.milliseconds)
val number = Random.nextInt(0..10)
log("Emitting $number!")
_messageFlow.emit(number)
}
}
}
}
- νλ‘μ° λΉλλ₯Ό μ¬μ©νλ λμ κ°λ³μ μΈ νλ‘μ°μ λν μ°Έμ‘°λ₯Ό μ»λλ€.
- λ°°μΆμ΄ ꡬλ μ μ 무μ κ΄κ³μμ΄ λ°μνλ―λ‘ μ¬λ¬λΆμ΄ μ€μ λ°°μΆμ μννλ μ½λ£¨ν΄μ μμν μ± μμ΄ μλ€.
fun main() = runBlocking {
RadioStation().beginBroadcasting(this)
}
- ꡬλ μκ° μμ΄λ λΈλ‘λμΊμ€νΈκ° μ¦μ μμ
fun main() = runBlocking {
val radioStation = RadioStation()
radioStation.beginBroadcasting(this)
delay(600.milliseconds)
radioStation.messageFlow.collect {
log("A collecting: $it!")
}
}
- μ½κ°μ μ§μ° νμ 곡μ νλ‘μ° κ΅¬λ
π οΈ κ΅¬λ μλ₯Ό μν κ° μ¬μ
- 곡μ νλ‘μ° κ΅¬λ μλ ꡬλ μ μμν μ΄νμ λ°°μΆλ κ°λ§ μμ
private val _messageFlow = MutableSharedFlow<Int>(replay = 5)
- μ΄μ μ λ°°μΆλ μμλ μμ νκΈ°λ₯Ό μνλ€λ©΄
replayνλΌλ―Έν° μ€μ
π οΈ shareInμΌλ‘ μ½λ νλ‘μ°λ₯Ό 곡μ νλ‘μ°λ‘ μ ν
fun querySensor(): Int = Random.nextInt(-10..30)
fun getTemperatures(): Flow<Int> {
return flow {
while (true) {
emit(querySensor())
delay(500.milliseconds)
}
}
}
- μΌμ ν κ°κ²©μΌλ‘ κ°μ λ°ν
fun celsiusToFahrenheit(celsius: Int) = celsius * 9.0 / 5.0 + 32.0
fun main() {
val temps = getTemperatures()
runBlocking {
launch {
temps.collect {
log("$it Celsius")
}
}
launch {
temps.collect {
log("${celsiusToFahrenheit(it)} Fahrenheit")
}
}
}
}
- μ¬λ¬λ² νΈμΆνλ €λ©΄ κ° μμ§μκ° μΌμμ λ 립μ μΌλ‘ μ§μ
fun main() {
val temps = getTemperatures()
runBlocking {
val sharedTemps = temps.shareIn(this, SharingStarted.Lazily)
launch {
sharedTemps.collect {
log("$it Celsius")
}
}
launch {
sharedTemps.collect {
log("${celsiusToFahrenheit(it)} Fahrenheit")
}
}
}
}
shareInν¨μλ₯Ό μ¬μ©νλ©΄ μ£Όμ΄μ§ μ½λ νλ‘μ°λ₯Ό ν νλ‘μ°μΈ 곡μ νλ‘μ°λ‘ λ³νν μ μλ€.- λλ²μ§Έ νλΌλ―Έν°
startedλ νλ‘μ°κ° μ€μ λ‘ μΈμ μμλΌμΌ νλμ§λ₯Ό μ μEagerlyλ νλ‘μ° μμ§μ μ¦μ μμLazilyλ 첫 λ²μ§Έ ꡬλ μκ° λνλμΌλ§ μμ§ μμWhileSubscribedλ 첫 λ²μ§Έ ꡬλ μκ° λνλμΌ μμ§μ μμνκ³ , λ§μ§λ§ ꡬλ μκ° μ¬λΌμ§λ©΄ νλ‘μ° μμ§μ μ·¨μ
- μ½νλ¦°μμλ μκ°μ΄ μ§λ¨μ λ°λΌ μ¬λ¬ κ°μ κ³μ°νλ μμ μ λ¨μν μ½λ νλ‘μ°λ‘ λ ΈμΆνκ³ , νμν λ μ½λ νλ‘μ°λ₯Ό ν« νλ‘μ°λ‘ λ³ννλ ν¨ν΄μ΄ μμ£Ό μ¬μ©λλ€.
π 16.3.2 μμ€ν μν μΆμ : μν νλ‘μ°
class ViewCounter {
private val _counter = MutableStateFlow(0)
val counter = _counter.asStateFlow()
fun increment() {
_counter.update { it + 1 }
}
}
fun main() {
val vc = ViewCounter()
vc.increment()
println(vc.counter.value)
}
- κ°μ λ°°μΆνλ
emitμ μ¬μ©νλ λμ , κ°μ κ°±μ νλupdateν¨μ μ¬μ©
π οΈ UPDATE ν¨μλ‘ μμ νκ² μν νλ‘μ°μ μ°κΈ°
fun increment() {
_counter.value++
}
valueλ κ°λ³ μμ±μ΄λκΉ μμ κ°μ΄ ꡬνν΄λ λ κΉ?- μ μ°μ°μ μμμ μ΄μ§ μλ€.
- μ¦, μ½λ£¨ν΄λ€μ΄ μ¬λ¬ μ€λ λμμ μ€νλκΈ° λλ¬Έμ λ¬Έμ κ° μλ€.
- μ΄λ νμͺ½μ μ¦κ° μ°μ°μ΄ 무ν¨ν
π οΈ μν νλ‘μ°λ κ°μ΄ μ€μ λ‘ λ¬λΌμ‘μ λλ§ κ°μ λ°°μΆνλ€: λλ±μ± κΈ°λ° ν΅ν©
enum class Direction { LEFT, RIGHT }
class DirectionSelector {
private val _direction = MutableStateFlow(Direction.LEFT)
val direction = _direction.asStateFlow()
fun turn(d: Direction) {
_direction.update { d }
}
}
fun main() = runBlocking {
val switch = DirectionSelector()
launch {
switch.direction.collect {
log("Direction now $it")
}
}
delay(200.milliseconds)
switch.turn(Direction.RIGHT)
delay(200.milliseconds)
switch.turn(Direction.LEFT)
delay(200.milliseconds)
switch.turn(Direction.LEFT)
}
0 [main @coroutine#2] Direction now LEFT
210 [main @coroutine#2] Direction now RIGHT
405 [main @coroutine#2] Direction now LEFT
- LEFT μΈμκ° νλ²λ§ νΈμΆμ΄ λλ€.
- μν νλ‘μ°κ° λλ±μ± κΈ°λ° ν΅ν©μ μννκΈ° λλ¬Έ
- κ°μ΄ μ€μ λ‘ λ¬λΌμ‘μ λλ§ κ΅¬λ μμκ² κ°μ λ°°μΆ
π οΈ stateIn μΌλ‘ μ½λ νλ‘μ°λ₯Ό μν νλ‘μ°λ‘ λ³ννκΈ°
fun main() = runBlocking {
val temps = getTemperatures()
runBlocking {
val tempState = temps.stateIn(this)
println(tempState.value)
delay(800.milliseconds)
println(tempState.value)
}
}
stateInμΌλ‘ μ½λ νλ‘μ°λ₯Ό μν νλ‘μ°λ‘ λ³νν μ μλ€.- μλ νλ‘μ°μμ λ°°μΆλ μ΅μ κ°μ νμ μ½μ μ μλ€.
π 16.3.3 μν νλ‘μ°μ 곡μ νλ‘μ°μ λΉκ΅
- μΌλ°μ μΌλ‘ μν νλ‘μ°λ 곡μ νλ‘μ°λ³΄λ€ λ κ°λ¨ν APIλ₯Ό μ 곡
class Broadcaster {
private val _messages = MutableSharedFlow<String>()
val messages = _messages.asSharedFlow()
fun beginBroadcasting(scope: CoroutineScope) {
scope.launch {
_messages.emit("Hello!")
_messages.emit("Hi!")
_messages.emit("Hola!")
}
}
}
fun main(): Unit = runBlocking {
val broadcaster = Broadcaster()
broadcaster.beginBroadcasting(this)
delay(200.milliseconds)
broadcaster.messages.collect {
println("Message: $it")
}
}
- 첫 λ²μ§Έ ꡬλ μκ° λνλκΈ° μ μ λͺ¨λ λ©μμ§λ₯Ό λ°°μΆνλ λΈλ‘λμΊμ€νΈ
- λ©μμ§λ₯Ό μΆλ ₯νμ§ μμ.
class Broadcaster {
private val _messages = MutableStateFlow<List<String>>(emptyList())
val messages = _messages.asStateFlow()
fun beginBroadcasting(scope: CoroutineScope) {
scope.launch {
_messages.update { it + "Hello!" }
_messages.update { it + "Hi!" }
_messages.update { it + "Hola!" }
}
}
}
fun main() = runBlocking {
val broadcaster = Broadcaster()
broadcaster.beginBroadcasting(this)
delay(200.milliseconds)
println(broadcaster.messages.value)
}
- μν νλ‘μ°λ μ 체 λ©μμ§ κΈ°λ‘μ 리μ€νΈλ‘ μ μ₯νλ©΄μ ꡬλ μκ° λͺ¨λ μ΄μ λ©μμ§μ μ½κ² μ κ·Όν μ μκ² ν μ μλ€.
π 16.3.4 ν« νλ‘μ°, μ½λ νλ‘μ°, 곡μ νλ‘μ°, μν νλ‘μ°: μΈμ μ΄λ€ νλ‘μ°λ₯Ό μ¬μ©ν κΉ?
ν 16.1 μ½λ νλ‘μ°μ ν« νλ‘μ° λΉκ΅
| μ½λ νλ‘μ° | ν« νλ‘μ° |
|---|---|
| κΈ°λ³Έμ μΌλ‘ λΉνμ±(μμ§μμ μν΄ νμ±νλ¨) | κΈ°λ³Έμ μΌλ‘ νμ±νλ¨ |
| μμ§μκ° νλ μμ | μ¬λ¬ ꡬλ μκ° μμ |
| μμ§μλ λͺ¨λ λ°°μΆμ λ°μ | ꡬλ μλ ꡬλ μμ μμ λΆν° λ°°μΆμ λ°μ |
| 보ν΅μ μλ£λ¨ | μλ£λμ§ μμ |
| νλμ μ½λ£¨ν΄μμ λ°°μΆ λ°μ(channelFlow μ¬μ© μ μμΈ) | μ¬λ¬ μ½λ£¨ν΄μμ λ°°μΆν μ μμ |
