Firestore与Firebase的离线问题

Dut*_*ers 12 android firebase firebase-realtime-database google-cloud-firestore

我将我的一个应用程序转换为新的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)
Run Code Online (Sandbox Code Playgroud)

最后,我从成功保存中获取文档ID并将其存储在首选项或本地数据库中供以后使用(在...内onSuccessListener)

一切都很好.直到失去网络连接.然后一切都崩溃了,因为任务永远不会完成,onSuccess/onFailure/onComplete监听器永远不会被调用.所以该应用程序只是挂起.

我通过在每次保存之前检查网络可用性来解决这个问题,然后通过创建没有任何监听器的任务来解决这个问题.我还使用UUID生成器在本地生成文档ID.

这个,BTW,不是应用程序与旧的firebase一起工作的方式.在这种情况下,一切都在离线时运行良好,我看到文件在应用程序上线时同步.

我对Firestore的解决方法似乎是一个可怕的黑客.有没有人想出更好的解决方案?

在没有连接的 情况下,在没有使用cloud firestore脱机调用addOnCompleteListener的情况下,请参阅有关插入/删除文档回调的相关Firestore数据库

小智 12

Cloud Firestore为我们提供了处理脱机数据的功能,但您需要使用"快照"(QuerySnapshot,DocumentSnapshot)来处理这种情况,遗憾的是它没有很好地记录.这是使用Snapshot处理案例的一些代码示例(我使用Kotlin Android):

更新数据:

db.collection("members").document(id)
  .addSnapshotListener(object : EventListener<DocumentSnapshot> {
      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)

      }
  })
Run Code Online (Sandbox Code Playgroud)

添加数据:

db.collection("members").document()
 .addSnapshotListener(object : EventListener<DocumentSnapshot> {
     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)

     }
 })
Run Code Online (Sandbox Code Playgroud)

删除数据:

db.collection("members").document(list_member[position].id)
   .addSnapshotListener(object : EventListener<DocumentSnapshot> {
       override fun onEvent(snapshot: DocumentSnapshot?,
                            e: FirebaseFirestoreException?) {
           if (e != null) {
               Log.w(ContentValues.TAG, "Listen error", e)
               return
           }
           snapshot?.reference?.delete()
       }
   })
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到代码示例:https://github.com/sabithuraira/KotlinFirestore和博客文章http://blog.farifam.com/2017/11/28/android-kotlin-management-offline-firestore-data-automatically -Sync-IT /


Ale*_*amo 2

当网络连接丢失(用户设备上没有网络连接)时, 和onSuccess()都不会onFailure()被触发。这种行为是有道理的,因为只有当数据已在 Firebase 服务器上提交(或拒绝)时,任务才被视为已完成。因此onSuccess()只有当任务成功完成时才会触发。

每次保存之前无需检查网络可用性。有一种解决方法可以轻松帮助您查看 Firestore 客户端是否确实无法连接到 Firebase 服务器,方法是enabling debug logging

FirebaseFirestore.setLoggingEnabled(true);
Run Code Online (Sandbox Code Playgroud)

将数据写入 Firestore 数据库的操作定义为signal completion一旦实际提交到后端即可。结果,这按预期工作:离线时它们不会发出完成信号。

请注意,Firestore 客户端内部保证您可以读取自己的写入,即使您不等待删除任务完成也是如此。Firestore 客户端旨在在没有互联网连接的情况下继续正常运行。因此,在没有互联网连接的情况下写入/删除数据库是可能的(根据设计),并且永远不会产生错误。