くうと徒然なるままに

モバイルアプリを作りながらバックエンドも作っています。

Firebase Readtime DB + Kotlin Coroutine でいい感じに使う

Firebase の Realtime Database 使ってますか?

firebase.google.com

問題点

基本的に Callback な作りなため Kotlin Coroutine との相性がよくない

Firebase Realtime Database で値を読み取る時には基本的には Callback スタイルなコードを書きます。

Kotlin Coroutine で使う場合には一手間かける必要があります。

suspendCoroutine を使い Callback スタイルをCoroutine スタイルに変える

suspendCoroutine を使うと 引数に取るラムダ式を実行し、外部から見たときは suspend Functions かつ任意のタイミングで値を返すことができる関数を作成できます。

suspendCoroutine - Kotlin Programming Language

全体像はこちら

// 元のコードのクラス名をTに置き換えてます。
private fun getDatabase(): Deferred<T> = GlobalScope.async {
    return@async suspendCoroutine<T> {
      database.reference.child("hoge")
        .addListenerForSingleValueEvent(object : ValueEventListener {
          override fun onCancelled(p0: DatabaseError) {
          }

          override fun onDataChange(snapshot: DataSnapshot) {
            it.resume(
              snapshot.children
                .map { it.getValue(T::class.java) }
                .filterNotNull()
            )
          }
        })
    }
  }