初学者向けKotlin Coroutines Flow

# 前置き

* 本資料は以下の方向けです
  * Flowって何だ、うめぇのか？
  * コルーチン？？
  * 周りでFlow使われてるけど、サッパリわからん…
  * 1日でFlowを何となく理解したい
* 以下の方は退屈かと思います
  * Flowを何となく理解した
  * Flowはいいぞ
  * Flow？あぁ、若い頃を思い出すな…

# Kotlin Coroutine Flowとは

* Kotlin Coroutinesの新しい非同期処理用ライブラリ
* RxやPromiseに似た記述ができる
* コールドストリーム！

## コールドストリームとは

* Subscribeされたら初めて動きだす、Observableなストリーム
* ストリーム...データを連続して送り出す型
* それ以上は、[RxのHotとColdについて](https://qiita.com/toRisouP/items/f6088963037bfda658d3)を参照

## 会社員に例えると

* 上司(Subscriber)が社員(Observable)を監視(Subscribe)する　~~←語呂がいい~~
* 社員は上司に状況を逐一報告（emit/send/offer）する
* 上司はそのうち監視をやめる(Dispose)

### ホットストリームな働き方

🧑‍🦰 Hotさん「さあ、上司いないけど仕事はじめようっと！」

※ **上司に監視されなくても働き始める**

🤵 上司「Hotさん、今どんな感じ？」
🧑‍🦰 Hotさん「はい、こういう状況です！」
🤵 上司「・・・なるほど」

🧑‍🦰 Hotさん「状況変わりました！」
🤵 上司「・・・なるほど」

※ **上司が見てる間、ずっと報告を出す**

🤵 上司「Hotさん、もういいよ」
🧑‍🦰 Hotさん「では、作業終了します！」

※ **上司に止められるまで働き続ける**

Hotさんは**何人の上司がいてもマイペースで、頭を使う量も変わりません**。

### コールドストリームな働き方

🧑‍🦱 Coldさん「・・・（ボーッとしている）」

※ **上司に監視されないと働かない**

🤵 上司「Coldさん、どんな感じ？」
🧑‍🦱 Coldさん「（やべ、上司だ！）今はじめますんで！…はい、こういう状況です」
🤵 上司「・・・なるほど」

🧑‍🦱 Coldさん「状況変わりました！」
🤵 上司「・・・なるほど」

※ **上司が見てる間、ずっと報告を出す**

🧑‍🦱 Coldさん「（上司いなくなったな…）作業終了します」

※ **上司がいなくなったら自分で働くのをやめる**

Coldさんは常に上司の目を気にしており、**上司が2人に増えると2倍頭を使います**。

### Hotさんの良いところと欠点

Hotさんのほうが気力に満ちて有能に見えますが、難点もあります。

* 良いところ
  * 上司がいなくても働ける（上司以外の人も報告を見れる）
  * 上司が増えても、使うリソースは変わらない
* 難点
  * ちゃんと止めてあげないと、必要ないときも働き続けてしまう

### Coldさんの良いところと欠点

部下としては少し不安なColdさんですが、プログラムとして、**必要ないときに働かないのは実は強力な利点**です。

* 良いところ
  * 必要ないときにリソースを使わない
  * 不要になったリソースを即時開放してくれる
* 難点
  * 上司が2人に増えたら、使うリソースも2倍に増えてしまう

### Kotlinでは

元々Kotlin社にはChannelというHotさんがいたが、FlowというColdさんが最近入社されました。

## Flowの基本的な使い方

* ビジネスロジックは無加工のデータを非同期に送る

```kotlin:CounterUseCase.kt
suspend fun countStream(): Flow<Int> = flow {
    repeat(100) { count ->
        delay(100)
        emit(count) // 0 1 2 3 4 ... 99
    }
}
```

* ViewModelがデータを受け取り、表示向けに加工する

```kotlin:CounterViewModel.kt
val showing = MutableLiveData<String>()

fun showCountEvenNumbersSquared() {
    viewModelScope.launch(Dispatchers.Main) {
        useCase.countStream()
            .drop(1)
            .filter { it % 2 == 0 }
            .map { (it * it).toString() }
            .take(5)
            .collect { count.value = it } // 4 16 36 64 100
    }
}
```

* Viewが表示する

```Kotlin:MainActivity.kt
counterViewModel.showCountEvenNumbersSquared()
```

```kotlin:activity_main.xml
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{counterViewModel.showing}" />
```

## 全体図

```
View    |  ViewModel    | UseCase〜深層
-----------------------------------------------
        |               |
入力    →  Coroutine起動 → 時間のかかる処理（非同期）
　　　      　|　　　　　　　　           |       ↓↓↓
描画  ←←←  出力データ加工 ←←← 出力データ送信（複数回）
        |               |
```

Flowにはオペレーターがたくさんあり、この左向き時のデータ加工に優れています。

# おすすめ参考リンク

なんとなくイメージを掴んだところで、より理解が進みそうな記事をいくつか紹介します。

## 5分でわかるFlow

* [5分でわかるKotlin Coroutines Flow](https://speakerdeck.com/sys1yagi/5fen-tewakarukotlin-coroutines-flow)

## Flowの便利さを実感する

* [Coroutines Flow で ジェネリック ズンドコキヨシ](https://qiita.com/aMasatoYui/items/60057f51d6e444231f96)

## ホットストリームなFlow！？SharedFlowとStateFlowとは

* [【Kotlin】SharedFlowとStateFlowを読み解く](https://qiita.com/tonionagauzzi/items/43dcb01f9f120e14cc23)

## ViewModelScopeの補足説明

* [ViewModelとKotlin Coroutinesの書き方あれこれ](https://satoshun.github.io/2019/12/android-viewodel-kotlin-coroutine/)

## Dispatcherの補足説明

* [メインセーフティでコルーチンを使用する](https://developer.android.com/kotlin/coroutines-adv?hl=ja#main-safety)

## 既存アプリへのFlow導入実例

* [今からAndroidにCoroutineを取り入れたときのアーキテクチャについて](https://dev.classmethod.jp/articles/android-droidkaigi-sample/)

## Jetpack ComposeとFlow

* [Jetpack ComposeでFlowを状態として扱う](https://tech.mokelab.com/android/compose/app/arch/flow.html)

## 公式ドキュメント

* [Flow - kotlinx-coroutines-core](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/)

# あとがき

本記事の内容が、技術書典12新刊の[ACCESSテックブック2](https://techbookfest.org/product/5187915669831680?productVariantID=5039132097118208)に収録されました！
2020年に書いた記事ですが、2022年6月現在も閲覧数がとても多く、勉強会スライドのままだと読みづらかったので、記事形式で書き直しました。
参考リンクの記事を提供してくださったみなさま、ありがとうございます。