BottleH Blog

Kotlin in Action - 16μž₯ ν”Œλ‘œμš°

    Tags

  • Kotlin
Kotlin in Action - 16μž₯ ν”Œλ‘œμš° thumbnail

πŸ“– 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 μ‚¬μš© μ‹œ μ˜ˆμ™Έ) μ—¬λŸ¬ μ½”λ£¨ν‹΄μ—μ„œ λ°°μΆœν•  수 있음
Written by@BottleH
Back-End Developer

GitHub