1
0

More than 3 years have passed since last update.

collbackFlowをFirebase Realtime Databaseに使うといい感じ

Posted at

概要

個人AndroidアプリでFirebase Realtime Database(略してRTDB)を使っているが、ValueEventListenerのコールバックで実装する書き方がイマイチ好きではなかった。

そこでcollbackFlow を使うと、RTDBとの接続をキレイに分離可能かつがStateFlow化できて、スッキリ書くことができた。
また、RTDBとの相性もよくて、値が何度も更新されてもFlowでちゃんと受け取れる。

コード: 状態管理

例として、天気を取得する機能を実装するコードを紹介する。

StateFlowで管理する状態クラス
今回は分かりやすいようにSuccess内の変数をWeatherInfoにしている

sealed class WeatherUiState {
    // 値の取得成功
    data class Success(val weatherInfo: WeatherInfo) : WeatherUiState()
    // 失敗
    data class Error(val message: String) : WeatherUiState()
}

コード: Repository

RTDBに接続して値を取得してくる

class WeatherRepository(private val dbRef: DatabaseReference) {

    /**
     * 天気を取得
     */
    @ExperimentalCoroutinesApi
    fun fetchWeather(): Flow<WeatherUiState> = callbackFlow { // callbackFlowの戻り値はFlow型
        // DBへの接続
        dbRef.addValueEventListener(object : ValueEventListener {
            // 正常に取得できた場合
            override fun onDataChange(snapshot: DataSnapshot) {
                snapshot.getValue(WeatherInfo::class.java)?.let { weather ->
                    // offerで購読側に値を流せる
                    offer(WeatherUiState.Success(weather))
                }
            }

            // エラーの場合
            override fun onCancelled(error: DatabaseError) {
                offer(WeatherUiState.Error(error.message))
            }
        })
        awaitClose {
            // 後始末はここでするが、DatabaseReferenceは自動で破棄されるで、やる事なし
        }
    }

コード: ViewModel

RepositoryのStateFlowを購読するだけ。

class WeatherViewModel : ViewModel() {

    private val _weather = MutableLiveData<WeatherInfo>()
    val weather :LiveData<WeatherInfo> = _weather

    @ExperimentalCoroutinesApi
    fun fetchWeather() {
        viewModelScope.launch {
            // StateFlowの購読
            weatherRepository.fetchWeather().collect { state ->
                when (state) {
                    // 成功
                    is WeatherUiState.Success ->  _weather.value = state.weatherInfo
                    // エラー処理
                    is WeatherUiState.Error -> // 画面にエラー通知など
                }
            }
        }
    }

感想

Flowの学習もかねてcallbackFlowを触ったが、すごくシンプルかつスッキリ書けていいね。

今回はFirebase RTDBと組み合わせたが、Firestoreにも同じように使えるはず。

あと、位置情報やBLEスキャンにcallbackFlowを使っている記事もあるので、けっこう便利に使えそう

参考リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0