簡體   English   中英

如何在 OnCompleteListener Firebase 中使用 Async/Await/Coroutines

[英]How To Use Async/Await/Coroutines In OnCompleteListener Firebase

我正在構建一個客戶端應用程序,它使用 Firebase 做兩件事:

  • 用戶認證
  • 使用實時數據庫

我設法在我的客戶端和后端服務器上正確設置了所有內容(使用 Firebase 的 Admin SDK),並且能夠正確驗證用戶並允許他們讀/寫數據庫。

我還使用 Retrofit2 將請求從客戶端發送到后端。

作為允許用戶訪問數據庫的一部分,需要將用戶的令牌發送到后端,以便可以驗證用戶。

為此,我有以下邏輯:

val user = FirebaseAuth.getInstance().currentUser

    if (user != null) {
        user.getIdToken(false).addOnCompleteListener {
            if (it.isSuccessful) {
                val token = it.result?.token
                //retrofit logic to send request happens from here
            }
       }

如您所見,獲取用戶的 Id 令牌是一個異步調用,在我擁有的當前代碼庫中,我對后端的每個調用(重復)都有這個代碼塊。

我想知道如何將這個片段導出到一個函數(也許是一個掛起方法?),以便它可以在每次調用后端時重復使用

我在網上搜索並看到了很多 SO 問題,但沒有一個適合這種情況。 我想過傳入回調,但是我有幾個方法與后端通信,每個方法都需要不同的回調方法。

我正在尋找的解決方案如下所示:

fun fetchDataFromDB() {
  getIdTokenForUser()
  //wait till it finishes and then
  //perform request to DB
}

fun updateDataInDB() {
  getIdTokenForUser()
  //wait till it finishes and then
  //perform request to DB
}

//......

我曾嘗試閱讀和實現協程,但我缺乏正確執行此操作的知識。

編輯

感謝@Doug Stevenson 的回答和指導,我設法構建了以下內容:

private suspend fun getUserIdToken(user: FirebaseUser) = coroutineScope {

    val job = async {
        user.getIdToken(false).result?.token
    }
    job.await()
}

我以這種方式使用它:

fun updateDB(context: Context) = runBlocking {

    val user = FirebaseAuth.getInstance().currentUser

    if (user != null) {
        val token = getUserIdToken(user)
    }

  }

這是正確的方法嗎? 由於下面給出的答案提出了不同的實現。

getIdToken是異步返回一個 Task 對象。 如果您想在 Kotlin 協程中使用 Task 對象,您可以使用庫kotlinx-coroutines-play-services向 Task 添加一個擴展方法await() ,使其在協程中可用。 有了這個,你可以寫這樣的東西:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.9"
import kotlinx.coroutines.tasks.await

suspend fun getIdTokenForUser(user: FirebaseUser): GetTokenResult {
    return try {
        user.getIdToken(false).await()
    }
    catch (e: Exception) {
        // handle error
    }
}

您可能需要在這里更新類型 - 我沒有嘗試編譯或測試它。

也可以看看:

為了從基於回調的 API 開始,如下所示:


val myCallback = object : ServiceCallback() {
    override fun onResult(theobject: Something) {
        // your callback code here
    }
    override fun onFailure(ex: Throwable) {
         // error handling
    }

}

theService.enqueue(callback)

您可以使用suspendCoroutine

它的作用是暫停執行,直到回調滿足延續。 所以你可以像下面這樣寫一個 KTX:

suspend fun Service.getSomething(): Something = suspendCoroutine{ cont ->
    val callback = object : ServiceCallback(){
         override fun onSuccess(data: Something): Unit = cont.resume(data)
         override fun onFailure(ex: Throwable): Unit = cont.resume(ex)
    }
    this.enqueue(callback)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM