[Android] Flowの基礎と使い分けをまとめてみた

スポンサーリンク

Kotlin Flowの基礎と使い分けをまとめてみた【StateFlow・SharedFlowも解説】

こんにちは、Friegenです。
今回は「Flow」について整理していきます。最近のAndroid開発では、もう欠かせない存在ですよね。
ただ、「Flowって種類が多くてよく分からない…」という声もよく聞きます。

この記事では、Flowの基本から、StateFlow・SharedFlowの違い、使い分け方までまとめて紹介します。


Flowとは?

まず、Flowは簡単に言うと「非同期で連続するデータを扱う仕組み」です。
RxJavaの Observable に近いですが、Kotlin標準のコルーチンと統合されていて、より軽量です。

例えば「サーバーからデータを取得して、UIに順に表示する」といった場面で便利です。


fun simpleFlow(): Flow = flow {
    for (i in 1..3) {
        delay(1000)
        emit(i)
    }
}

// collectで受け取る
GlobalScope.launch {
    simpleFlow().collect { value ->
        Log.d("FlowSample", "値 = $value")
    }
}

この例では、1秒ごとに1, 2, 3 と値をemitして、collect側で受け取っています。


Cold Flow と Hot Flow の違い

Flowには大きく分けて2種類あります。

  • Cold Flow: collectされるたびに最初から実行される
  • Hot Flow: 常にデータを流していて、途中から購読すると最新値や途中の値を受け取る

例えば上の simpleFlow() はCold Flowです。
collect()するたびに新しく1,2,3をemitします。

一方、StateFlowSharedFlowはHot Flowです。
すでに流れているデータを途中から購読してもOK。


StateFlowとは?

StateFlow は「常に最新の状態を保持するFlow」です。
LiveDataに近い動きをします。


// ViewModel内
private val _uiState = MutableStateFlow("初期状態")
val uiState: StateFlow<String> = _uiState

fun updateState(newText: String) {
    _uiState.value = newText
}

そしてUI側でcollectします:


lifecycleScope.launch {
    viewModel.uiState.collect { state ->
        binding.textView.text = state
    }
}

StateFlowのポイント:

  • 常に最新値(state)を保持する
  • 新しいcollectが来た時も直近の値を即座に受け取れる
  • 初期値が必須

UIの状態管理(ボタン押下、入力フォームなど)に最適です。


SharedFlowとは?

SharedFlow は「イベントの発火・共有」に使われます。
StateFlowのように「状態」ではなく「出来事(Event)」を扱いたい時に便利です。


// ViewModel内
private val _eventFlow = MutableSharedFlow<String>()
val eventFlow = _eventFlow.asSharedFlow()

fun sendEvent(message: String) {
    viewModelScope.launch {
        _eventFlow.emit(message)
    }
}

そしてUI側:


lifecycleScope.launch {
    viewModel.eventFlow.collect { msg ->
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
    }
}

SharedFlowの特徴:

  • 値を保持しない(初期値なし)
  • イベント的に扱える
  • 複数のcollect先に同時に通知可能

ログイン成功イベント、ダイアログ表示トリガーなどに向いています。


StateFlowとSharedFlowの使い分け

項目StateFlowSharedFlow
用途UI状態の保持一度きりのイベント通知
初期値必要不要
最新値保持ありなし
ボタンON/OFF、フォーム入力Toast、ナビゲーションイベント

Flowの変換・操作関数も押さえておこう

Flowは、Rxと同じようにmapやfilterなども使えます。


flowOf(1, 2, 3, 4, 5)
    .filter { it % 2 == 0 }
    .map { "偶数: $it" }
    .collect { Log.d("FlowSample", it) }

結果:


偶数: 2
偶数: 4

Flowを扱うときは、UIスレッドではなくDispatchers.IOなどで処理を行うようにしましょう。


まとめ

  • Flow:非同期データストリームの基本
  • Cold Flow:collectごとに新規実行
  • Hot Flow:常にデータを流す(StateFlow・SharedFlow)
  • StateFlow:状態を保持(UI状態管理向け)
  • SharedFlow:イベント通知向け

Flowを使いこなすと、UIと非同期処理のやりとりがかなりスッキリします。
RxJava時代の「購読解除忘れ」も減るので、モダンな開発を目指すなら避けて通れない部分ですね。


次回は、「FlowをRoom・Retrofitと組み合わせる」あたりを掘り下げてみようと思います。

ではまた。

コメント

タイトルとURLをコピーしました