Firestore runTransaction()和脱机工作

Vad*_*ovs 7 android firebase google-cloud-firestore

我正在使用事务在Firestore中实现post喜欢和评论功能.我使用事务是因为我需要在帖子中的likes/comments子集和更新计数器中添加新字段,并且还将post id添加到用户喜欢/评论的帖子集合中.

我注意到如果我离线了,我就像这样请求我的帖子一切正常:

val postDocRef = FirebaseUtil.postsColRef.document(postId)

postDocRef.get().addOnSuccessListener { doc ->
    val post = doc.toObject(Post::class.java)
    Timber.e(post.toString())
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我在事务中执行相同的异常抛出:

val postDocRef = FirebaseUtil.postsColRef.document(postId)

FirebaseUtil.firestore.runTransaction(Transaction.Function<Void> { transaction ->
    val post = transaction.get(postDocRef).toObject(Post::class.java)
}
Run Code Online (Sandbox Code Playgroud)

例外情况是:

com.google.firebase.firestore.FirebaseFirestoreException:UNAVAILABLE

为什么离线模式在交易中不起作用?是否可以在离线状态下实现此功能(在子集合中添加条目并在不同对象中更新字段)?

continueWithTask()调用链替换事务有什么缺点?

SUP*_*LEX 8

不,这对于交易是不可能的,因为它们本质上是网络相关的.当您使用事务时,您告诉Firestore您只能同步执行数据库操作,一个客户端接着另一个客户端.交易对于游戏中的货币转移等内容非常有用,您需要确保不会意外地将写入加倍并给用户太多或太少的钱.

如果您的类似计数器需要具有完美的精度,我建议使用子集合,其中每个文档包含对喜欢给定帖子的用户的引用.然后,在云功能中,您可以使用事务来计算喜欢帖子的用户数量,并确保没有错误计数.这有一个额外的好处,让你知道谁喜欢一个应该是未来证明的帖子,如果你决定添加更多相关的功能.在客户端,即使您没有权限,也可以通过写入计数器来"欺骗"它.我没有测试过这个,但我很确定写入会在本地成功,然后只有在你重新上线后才会失败.这无关紧要,因为云功能将同步计数器服务器端.

另一方面,如果你真的不关心具有超精确的计数,你正在寻找的是WriteBatch课程.这是Firestore中的新功能,非常酷.我正在写一篇关于我发表的Firestore的帖子,但这里有一段摘录:

Cloud Firestore还包含一种与WriteBatch该类批量写入的强大新方法.它与SharedPreferences.Editor您在Android上找到的非常相似 .您可以在WriteBatch实例中添加或更新文档,但在调用之前,您的应用程序将无法看到这些文档WriteBatch#commit().我已经创建了标准的Kotlin改进,可以为您管理批量生命周期 - 随意使用copypasta.

inline fun firestoreBatch(transaction: WriteBatch.() -> Unit): Task<Void> = FirebaseFirestore.getInstance().batch().run {
    transaction()
    commit()
}
Run Code Online (Sandbox Code Playgroud)