Как получить данные из Firebase Database?

Есть функция:

fun DatabaseReference.takeAll(): Any {

    this.addValueEventListener(object : ValueEventListener {

        override fun onDataChange(snapshot: DataSnapshot) {
            if (snapshot.exists()) {
                val counter = snapshot.childrenCount
                if (counter > 1) {
                    val list: MutableList<String>? = null
                    for (i in snapshot.children) {
                        list?.add(i.key.toString())
                    }
                } else if (counter == 1L) {
                    val data = snapshot.value.toString()
                }
            } else {
                Log.e(TAG, "Take All Function: snapshot is not exist")
            }
        }

        override fun onCancelled(error: DatabaseError) {
            Log.e(TAG, error.message)
        }

    })

}

Её задача — достать данные из БД по определенному пути и вернуть мне их.

У меня несколько вопросов:

  1. Что писать как возвращаемое значение, т. к. оно может быть и списком и просто строкой.

  2. Как в конце функции вернуть значение только когда данные полностью загрузятся, чтобы после вызова я их записал и пошел дальше работать.

Пробовал вернуть в for или в else if, но ругается на то, что функция onDataChange должна возвращать Unit. При попытке вернуть не Unit ругается на override, что предсказуемо.

Запускается функция из main-потока, но можно реализовать её как корутину. Вызывать я планирую её примерно вот так:

val data = путь.takeAll()

И дальше какие то действия с ней.


Ответы (1 шт):

Автор решения: Vadik

По документации Firebase, чтобы единоразово вытащить данные из базы, нужно выполнить следующий код:

database.child("users").child(userId).get()
    .addOnSuccessListener { data ->
        println("Пользователь: ${data.value}")
    }
    .addOnFailureListener { exception ->
        println("Не удалось получить пользователя из базы")
        exception.printStackTrace()
    }

Для удобной интеграции Tasks API с корутинами есть расширение kotlinx-coroutines-play-services. Экстеншен await() упростит работу с отложенными Task. Тот же самый код будет выглядеть так:

try {
    val data = database.child("users").child(userId).get().await()
    println("Пользователь: ${data.value}")
} catch (exception: Exception) {
    println("Не удалось получить пользователя из базы")
    exception.printStackTrace()
}

Экстеншен await() является suspend-функцией, поэтому может быть вызван только из другой suspend-функции либо из корутины.

→ Ссылка