Как использовать сопрограммы kotlin в базе данных Firebase - PullRequest
0 голосов
/ 17 марта 2019

Я пытаюсь получить доступ к комнате чата, используя firestore и сопрограммы.

    fun getOwner() {
        runBlocking {
            var de = async(Dispatchers.IO) {
                firestore.collection("Chat").document("cF7DrENgQ4noWjr3SxKX").get()
            }
            var result = de.await().result
        }

Но я получаю сообщение об ошибке, подобное этому:

E/AndroidRuntime: FATAL EXCEPTION: Timer-0
    Process: com.example.map_fetchuser_trest, PID: 19329
    java.lang.IllegalStateException: Task is not yet complete
        at com.google.android.gms.common.internal.Preconditions.checkState(Unknown Source:29)
        at com.google.android.gms.tasks.zzu.zzb(Unknown Source:121)
        at com.google.android.gms.tasks.zzu.getResult(Unknown Source:12)
        at com.example.map_fetchuser_trest.model.Repository$getOwner$1.invokeSuspend(Repository.kt:53)

Как я могу получить документ чата?когда я использую исходный API, как показано ниже, я могу получить доступ к документу чата.

        firestore.collection("Chat").document(
            "cF7DrENgQ4noWjr3SxKX"
        ).get().addOnCompleteListener { task ->
            if (task.isSuccessful) {
                val chatDTO = task.result?.toObject(Appointment::class.java)
            }
        }

Ответы [ 2 ]

5 голосов
/ 17 марта 2019

Task - это то, чего вы ждете, но вы завернули его в другой слой async. Удалить async:

fun getOwner() {
    runBlocking {
        var de =  firestore.collection("Chat").document("cF7DrENgQ4noWjr3SxKX").get()
        var result = de.await().result
    }
}

Однако, используя runBlocking(), вы попали себе в ногу и написали код блокировки, который просто формально использует асинхронный API, но безрезультатно.

Чтобы по-настоящему извлечь из этого пользу, вы должны иметь

suspend fun getOwner() = firestore
     .collection("Chat")
     .document("cF7DrENgQ4noWjr3SxKX")
     .get()
     .await()
     .result

и launch сопрограмма в том месте, откуда вы ее называете:

launch {
    val owner = getOwner()
    // update the GUI
}

Предполагается, что вы вызываете launch с объекта, который является CoroutineScope.

2 голосов
/ 17 марта 2019

Использование runBlocking{..} в первом фрагменте кода работает следующим образом: функция runBlocking блокирует для выполнения лямбда-кода параметра (и лямбда-код будет приостановлен внутри). Это дает меньше смысла.

Возможно, вы захотите запустить сопрограмму с функцией launch{..} и использовать withContext(Dispatchers.Main){..} для выполнения блока в потоке пользовательского интерфейса, например, чтобы показать полученные результаты. Вы также можете реализовать CoroutineScope в своем классе деятельности.

Первый шаг - вам нужно превратить вызов API Firebase в функцию приостановки. Это можно сделать с помощью функции suspendCoroutine{..} (в библиотеке kotlinx.coroutines есть еще несколько функций, таких как suspendCancellableCoroutine{..}.

Существует библиотека интеграции со Службами Google Play, которая обеспечивает поддержку Firebase
https://github.com/Kotlin/kotlinx.coroutines/tree/master/integration/kotlinx-coroutines-play-services

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...