Firestore与Firebase的离线问题
我将其中一个应用程序转换为新的Firestore。 我正在做一些事情,像点击一个按钮保存文档,然后在onSuccess
监听器,去一个不同的活动。
我还使用Firestore保存操作返回任务的事实,使用Tasks.whenAll
将任务组合在一起:
val allTasks = Tasks.whenAll( createSupporter(supporter),, setStreetLookup(makeStreetKey(supporter.street_name)), updateCircleChartForUser(statusChange, createMode = true), updateStatusCountForUser(statusChange)) allTasks.addOnSuccessListener(this@SignUpActivity, successListener) allTasks.addOnFailureListener(this@SignUpActivity, onFailureListener)
最后,我从成功的保存中获取文档ID,并将其存储在首选项或本地数据库中供以后使用(在onSuccessListener
)
这一切都很好。 直到网络连接中断 。 然后,一切都崩溃了,因为任务永远不会完成,onSuccess / onFailure / onComplete监听器永远不会被调用。 所以应用程序只是挂起。
我正在通过在每次保存之前检查网络可用性来解决此问题,然后通过创建没有任何侦听器的任务来解决此问题。 我也使用UUID生成器在本地生成文档ID。
顺便说一句,这不是应用程序与旧的firebase的工作方式。 在这种情况下,离线时,一切都运行良好,每当应用程序上线时,我都会看到文件同步。
我的Firestore的解决方法似乎是一个可怕的黑客攻击。 有没有人想出更好的解决方案?
有关插入/删除文档回调的相关Firestore数据库在没有连接时不会被调用 addOnCompleteListener不会与云端firestore脱机调用
Cloud Firestore为我们提供了处理离线数据的function,但是您需要使用“Snapshot”(QuerySnapshot,DocumentSnapshot)来处理这种情况,遗憾的是,它没有很好的记录。 这是一些代码示例(我使用Kotlin Android)使用快照处理案例:
更新数据:
db.collection("members").document(id) .addSnapshotListener(object : EventListener { override fun onEvent(snapshot: DocumentSnapshot?, e: FirebaseFirestoreException?) { if (e != null) { Log.w(ContentValues.TAG, "Listen error", e) err_msg.text = e.message err_msg.visibility = View.VISIBLE; return } snapshot?.reference?.update(data) } })
添加数据:
db.collection("members").document() .addSnapshotListener(object : EventListener { override fun onEvent(snapshot: DocumentSnapshot?, e: FirebaseFirestoreException?) { if (e != null) { Log.w(ContentValues.TAG, "Listen error", e) err_msg.text = e.message err_msg.visibility = View.VISIBLE; return } snapshot?.reference?.set(data) } })
删除数据:
db.collection("members").document(list_member[position].id) .addSnapshotListener(object : EventListener { override fun onEvent(snapshot: DocumentSnapshot?, e: FirebaseFirestoreException?) { if (e != null) { Log.w(ContentValues.TAG, "Listen error", e) return } snapshot?.reference?.delete() } })
你可以在这里看到代码示例: https : //github.com/sabithuraira/KotlinFirestore和博客文章http://blog.farifam.com/2017/11/28/android-kotlin-management-offline-firestore-data-automatically -Sync-IT /
我发现如何使用http://blog.farifam.com上的信息。 基本上,您必须使用SnapshotListeners
而不是OnSuccess
侦听器进行脱机工作。 另外,您不能使用Google的任务,因为它们不会脱机。
相反(因为任务基本上都是Promises),所以我使用了Kotlin Kovenant库,它可以把听众附加到承诺上。 一个wrinke是你必须配置Kovenant允许一个承诺的多个解决方案,因为事件监听器可以被调用两次(一旦数据被添加到本地缓存,一旦它被同步到服务器)。
这是一个代码片段,带有成功/失败的监听器,可以在线和离线运行。
val deferred = deferred() // create a deferred, which holds a promise // add listeners deferred.promise.success { Log.v(TAG, "Success! docid=" + it.id) } deferred.promise.fail { Log.v(TAG, "Sorry, no workie.") } val executor: Executor = Executors.newSingleThreadExecutor() val docRef = FF.getInstance().collection("mydata").document("12345") val data = mapOf("mykey" to "some string") docRef.addSnapshotListener(executor, EventListener { snap: DocumentSnapshot?, e: FirebaseFirestoreException? -> val result = if (e == null) Result.of(snap) else Result.error(e) result.failure { deferred.reject(it) // reject promise, will fire listener } result.success { snapshot -> snapshot.reference.set(data) deferred.resolve(snapshot) // resolve promise, will fire listener } })
当网络连接中断(用户设备上没有网络连接)时, onSuccess()
和onFailure()
都不会被触发。 这种行为是有道理的,因为只有在Firebase服务器上提交(或拒绝)数据时才认为该任务已完成。 onComplete(Task
方法仅在任务完成时调用。 所以在没有互联网连接的情况下, onComplete
都不会被触发。
每次保存前无需检查网络可用性。 有一种解决方法可以帮助您查看Firestore客户端是否确实无法连接到Firebase服务器,即通过enabling debug logging
:
FirebaseFirestore.setLoggingEnabled(true);
将数据写入Firestore数据库的操作被定义为一旦实际提交到后端就signal completion
。 因此,这是按预期工作的:离线时,他们不会发出完成信号。
请注意,即使您不等待完成删除任务,Firestore客户端也会保证您可以读取自己的写入内容。
- Firebase @Exclude with kotlin data class
- Firebase Android – 在Kotlin中使用电子邮件和密码创建用户
- Firebase Perf不会运行测试应用程序:transformClassesWithFirebasePerformancePluginForDebugAndroidTest
- 移除Firebase侦听器不适用于Android
- 如何从Firebase中的表中同步获取所有行?
- 如何在Firebase中创建多个孩子
- 如何处理iOS中的Firebase数据库错误? #AskFirebase
- FirebaseDatabase根引用在事务中为空
- 在android中加载页面加载firebase数据