android - 如何在 OnCompleteListener Firebase 中使用 Async/Await/Coroutines
问题描述
我正在构建一个使用 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
}
}
您可能必须在此处更新类型 - 我没有尝试编译或测试它。
也可以看看:
推荐阅读
- android - 如何在android中合并音频和视频
- android - 如何在一次下载多个文件时添加百分比进度条
- java - 在 Codeception 中添加自定义请求标头
- python-3.x - Pytorch - 这是使用 pytorch.data.Dataset 加载大数据集并对其进行线性回归训练的正确方法吗
- c# - 尝试创建抽象层以支持多个第三方作为文档管理系统
- r - 如何使用 felm() 指定工具变量模型?
- mysql - 填空 ID MySQL
- php - 如何从附件描述wordpress中获取peragraph的关键字?
- python - Pandas 强制对包含重复键的列进行一对一合并
- mysql - 如何在 AFTER UPDATE 触发器中引用最近更新的行