Kotlin Coroutines Flow を触ってみた話し

F46a37b9f855c245f72a07b04045216a?s=47 Tomoya Miwa
September 14, 2019

Kotlin Coroutines Flow を触ってみた話し

F46a37b9f855c245f72a07b04045216a?s=128

Tomoya Miwa

September 14, 2019
Tweet

Transcript

  1. 2.

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

    iOS DroidKaigi staff (since DroidKaigi 2019) DeNA Co., Ltd. Automotive Business Unit.
  2. 4.

    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. 9.

    簡単な使い⽅ val myFlow = flow { // flow builderの⼀つ emit(1)

    emit(2) } GlobalScope.launch { myFlow.collect { value -> println("Received $value") // Received 1 // Received 2 } }
  4. 11.

    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. 12.

    こうすれば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. 16.

    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. 19.

    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) } } }
  8. 23.