Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin Coroutines Flow を触ってみた話し

Tomoya Miwa
September 14, 2019

Kotlin Coroutines Flow を触ってみた話し

Tomoya Miwa

September 14, 2019
Tweet

More Decks by Tomoya Miwa

Other Decks in Programming

Transcript

  1. About me tomoya0x00 Twitter, GitHub, Qiita Android, Embedded system, BLE/BT,

    iOS DroidKaigi staff (since DroidKaigi 2019) DeNA Co., Ltd. Automotive Business Unit.
  2. Kotlin Coroutines Flow is 何︖ https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines- core/kotlinx.coroutines. ow/ Flow —

    asynchronous cold stream of elements. RxJavaみたいなもの 最近、kotlinx-coroutines-core:1.3.0でstableになった ただし、⼀部はまだexperimentalだったりpreviewだったり @ExperimentalCoroutinesApi @FlowPreview
  3. 簡単な使い⽅ val myFlow = flow { // flow builderの⼀つ emit(1)

    emit(2) } GlobalScope.launch { myFlow.collect { value -> println("Received $value") // Received 1 // Received 2 } }
  4. NGな使い⽅ suspend fun hoge() = 2 val myFlow = flow

    { emit(1) // OK withContext(Dispatchers.IO) { emit(hoge()) // NG(collectする側のコンテキストの強制指定はダメ) } } GlobalScope.launch { myFlow.collect { value -> println("Received $value") } }
  5. こうすればOK suspend fun hoge() = 2 val myFlow = flow

    { emit(1) // OK val result = withContext(Dispatchers.IO) { hoge() } emit(result) // OK } GlobalScope.launch { myFlow.collect { value -> println("Received $value") } }
  6. collectしている間、動き続けるFlow シリアル通信で受信したデータをひたすらFlowで流したい シリアル通信のread()はブロッキングI/O val received: Flow<ByteArray> = flow { coroutineScope

    { // coroutineScopeでくくると、 while (isActive) { // isActiveでキャンセルされたことが検知できる val data = withContext<ByteArray>(Dispatchers.IO) { read() } emit(data) } } }
  7. val isAvailable: Flow<Boolean> = flow { coroutineScope { while (isActive)

    { val available = withContext<Boolean>(Dispatchers.IO) { var receivedAck = false // 1sec間隔で5回pingして、1回でも応答有れば利⽤可能と判定 repeat(5) { try { delay(1000L) ping() receivedAck = true } catch (e: Exception) { // Do nothing } } receivedAck } emit(available) } } }