【问题标题】:How to read Firebase realtime database value synchronously?如何同步读取 Firebase 实时数据库值?
【发布时间】:2018-10-05 08:52:36
【问题描述】:

我正在使用 firebase 实时数据库,据我所知,您必须使用

 DatabaseReference.addValueEventListener

从 firebase 数据库中读取值。

这里addValueEventListener默认是异步的。我需要同步阅读。对于 FireBase 存储,对于上传文件时的相同问题,我可以通过使用使过程同步

     UploadTask.TaskSnapshot await = Tasks.await(uploadTask);

而不是使用

     uploadTask.addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
                                                    @Override
                                                    public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {

                                                    }
                                                })          

如上所示,addValueEventListener 是否有任何类似的同步替代方案?

【问题讨论】:

  • 尝试从异步 API 同步返回值,这不是一个好主意。您应该按预期异步处理 API。你想通过这种方式得到答案吗?
  • 我这样做是因为我在一个已经异步的块中使用这个函数。
  • 这个有同步版本吗?
  • 在你的应用程序的主线程中调用同步方法可能会完全冻结你的应用程序,这是一种糟糕的用户体验。在 Android 上,您最终可能还会收到 Application Not Responding 对话框。这是你想要的吗?
  • 一个addValueEventListener 可以触发多次,所以没有完成。但是addSingleValueEventListener可以完成。请参阅Doug's blost post here,了解如何将addListenerForSingleValueEvent 转换为您可以等待的Task

标签: android firebase firebase-realtime-database


【解决方案1】:

尝试从异步 API 同步返回值,这不是一个好主意。但如果您的块已经与主线程异步 - 您可以使用 CountDownLatchawait 回调响应。

例子:

CountDownLatch latch = new CountDownLatch(1);
uploadTask.addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>(){
       @Override
       public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
            //Handle response
            latch.countDown();
       }
});
latch.await();

【讨论】:

  • 这很棒。我想知道开发人员在处理服务器端逻辑和使用 firebase admin sdk 时如何编写代码。在开始新的聊天组之前,我有一种情况要检查用户的现有聊天,我发现这个答案很有用。
【解决方案2】:

大多数 firebase 方法都返回一个 Task 的实例。因此,我们可以轻松地在非主线程中等待它们以就地获取结果(而不是实现 onCompleteListener 并运行到“回调地狱”)。

但是我没有找到一种返回任务的 getValue 方法。我发现问题的 cmets 中提到了this blogpost。在经历了这些之后,我为自己编写了一个 getValue 扩展函数。

internal fun DatabaseReference.getValue(): Task<DataSnapshot> {
    val dbSource = TaskCompletionSource<DataSnapshot>()

    addListenerForSingleValueEvent(object : ValueEventListener {
        override fun onDataChange(snapshot: DataSnapshot) {
            dbSource.setResult(snapshot)
        }

        override fun onCancelled(error: DatabaseError) {
            dbSource.setException(error.toException())
        }
    })

    return dbSource.task
}

另外,如果有任何更正,请在 cmets 中告知:)

【讨论】:

    猜你喜欢
    • 2018-06-29
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 2021-02-18
    • 2022-10-07
    • 1970-01-01
    相关资源
    最近更新 更多