使用 Firebase 和 Kotlin 协程在 Android 中向 flatMapLatest 添加加载状态

Adding Loading States to flatMapLatest in Android with Firebase and Kotlin Coroutines

提问人:Collaxd 提问时间:11/17/2023 最后编辑:Frank van PuffelenCollaxd 更新时间:11/17/2023 访问量:19

问:

我正在开发一个利用 Firebase 进行身份验证和数据存储的 Android 项目。该项目遵循 Firebase 文档中的 MakeItSoApp 模型,并通过捕获错误的全局类处理 Crashlytics 错误。出于这个原因,我不太担心应用程序中 API 调用的 try-catch 块,因为它们将在稍后处理。

话虽如此,我的代码一直运行良好。它有一个用户,我需要读取的所有项目都有一个“userId”字段,该字段对应于将其保存在数据库中的用户。

下面是用户结构的示例:

class AccountServiceImpl @Inject constructor(
    private val auth: FirebaseAuth

) : AccountService {
    override val currentUser: Flow<User>
        get() = callbackFlow {
            val listener = FirebaseAuth.AuthStateListener { auth ->
                this.trySend(auth.currentUser?.let { User(it.uid) } ?: User())
            }
            auth.addAuthStateListener(listener)
            awaitClose { auth.removeAuthStateListener(listener) }
        }
}

读取数据继续以这种方式工作。

在服务类中...

@OptIn(ExperimentalCoroutinesApi::class)
class ProductStorageServiceImpl @Inject constructor(
    private val firestore: FirebaseFirestore,
    private val accountService: AccountService
) : ProductStorageService {
    override val products: Flow<List<Product>>
        get() = accountService.currentUser.flatMapLatest { user ->
            firestore.collection(PRODUCTS_COLLECTION).whereEqualTo(USER_ID_FIELD, user.id)
                .dataObjects()
        }

    override suspend fun add(product: Product) {
        val productWithUserId = product.copy(userId = accountService.currentUserId)
        firestore.collection(PRODUCTS_COLLECTION).add(productWithUserId).await()
    }
}

后跟 ViewModel 类...

    var products: Flow<List<Product>> = productStorageService.products

最后,UI 收集项目...

    val products by viewModel.products.collectAsStateWithLifecycle(emptyList())

完成此设置后,我遇到了以下问题。首先,我不太明白为什么当我添加产品时,我的阅读屏幕会更新,因为我只在屏幕中收集它,而 flatMapLatest 正在倾听用户的声音。这让我感到困惑,但它只是有效。现在,我想在我的流程中添加一个加载状态,类似于著名的 Resources 类:

sealed class Resource<T>(
    val data: T? = null,
    val message: String? = null,
) {
    class Success<T>(data: T) : Resource<T>(data)
    class Loading<T> : Resource<T>()
}

但是,我没有 Flow;我有一个flatMapLatest...

accountService.currentUser.flatMapLatest

...我唯一有流程的地方是在用户中,但我认为这是不正确的,而且考虑到数据来自另一个类,实际上是不可能的。 提前感谢您的任何指导或建议!

Android Kotlin google-cloud-firestore firebase-authentication kotlin-协程

评论

0赞 Alex Mamo 11/17/2023
我不确定我是否理解。此代码中究竟有哪些内容不符合您的预期?
0赞 Collaxd 11/18/2023
我希望您可以在数据库调用中使用“resource”类作为我的应用程序的加载状态。@AlexMamo
0赞 Alex Mamo 11/18/2023
这门课对我来说看起来不错。这是怎么回事?Resource
0赞 Collaxd 11/20/2023
我只想从我的flatMapLatest中发出资源
0赞 Alex Mamo 11/20/2023
究竟什么没有按照你期望的方式工作?

答: 暂无答案