【问题标题】:Firebase ChildEventListener if no data has been retrievedFirebase ChildEventListener(如果没有检索到数据)
【发布时间】:2017-03-08 11:52:24
【问题描述】:

我在我的应用中使用 Firebase。我有一个要使用此代码检索的元素列表:

FirebaseDatabase.getInstance()
.getReferenceFromUrl("myUrl")
.orderByChild("timestamp")
.addChildEventListener(this);

了解 ref url 内部是否没有数据的最佳方法是什么?因为使用 ChildEventListener 是不可能的。

ChildEventListener 只有这 4 个方法:onChildAdded()、onChildChanged()、onChildRemoved()、onChildMoved()

如果您的对象内部没有项目,则不会调用这些方法。

所以我的问题是。我也必须使用 ValueEventListener 吗? 我猜如果没有找到项目,就会调用 onDataChange()

一种可能的情况: 您有一个要使用 ChildEventListener 检索和填充的项目列表。 您想覆盖没有检索到任何项目的情况。所以显示文本“无数据”而不是列表。

【问题讨论】:

  • 在函数中尝试:datasnapshot.getChildrenCount()。如果为 0 则没有项目
  • 是的,我就是这么想的。所以你必须同时使用 ChildEventListener 和 ValueEventListener?
  • dataSnapshot in ChildEventListenerValueEventListener 产生的dataSnapshot 深一层,所以很遗憾这不起作用

标签: android firebase firebase-realtime-database


【解决方案1】:

据我所知,如果您通过 addChildEventListeneraddValueEventListener 在同一数据路径上直接请求数据(在代码中),您将首先完成 addChildEventListener 的结果,然后是 @987654325 @ inside ValueEventListener 将被执行。

所以我的解决方案是这样的:

Boolean childExist = false;

ref.addChildEventListener(new ChildEventListener() {
    ... onChildAdded() {
        // you can use List or Map here, this Boolean just to indicate if child exist or not
        childExist = true;
    }
    ...
})
ref.addValueEventListener(new ValueEventListener() {
    ... onDataChange() {
        // code you place here will be executed AFTER all of the event inside ChildEventListener is done
        // here the value of childExist will really indicate if there is child or no
    }
    ...
});

【讨论】:

  • 这可能是我们在 Java 上可以获得的最接近的解决方案(这太愚蠢了,因为 Javascript Firebase 有 $loaded 回调),但我假设这会两次获取整个数据集合......跨度>
  • 你能回答这个与firebase相关的问题吗:stackoverflow.com/q/46605342/6144372
【解决方案2】:

您始终可以只使用 valueEventListener 和 onDataChange 来检查 datasnapshot.exists() 是否存在。与这里的 javadoc 一致 -> https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#exists

在你的情况下

    FirebaseDatabase.getInstance()
        .getReferenceFromUrl("myUrl")
        .orderByChild("timestamp")
    .addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
        if (dataSnapshot.exists()){
        //Show text retrieved


         } else {
    //Show "No data"
    }
        }
@Override
public void onCancelled(DatabaseError databaseError) {
 Log.v(FB_ERROR_TAG, "Error in Database Connection");
}
 });

【讨论】:

    【解决方案3】:

    如果您只想在没有结果时显示“无数据”,您可以将标签的文本值默认设置为“无数据”,然后让 firebase 查询覆盖它。如果没有结果,它就不会被覆盖。

    【讨论】:

    • 是的,这是正确的,但是如果您在加载过程中有进度条?如何知道何时移除进度条并显示文本?
    • 我猜在这种情况下,您只需将 SingleValueEventListener 与 ChildEventListener 结合使用
    【解决方案4】:

    对于那些寻求反应式解决方案的人来说,唯一可用的似乎是在 databaseReference 缓存和您的缓存列表(处理您的 childEventListener 更改的那个)之间建立直接通信。

    考虑一下...当databaseReference保持不变时,缓存的List照常保持不变,相应地处理来自childEventListener的更改。

    一旦出现引用更改的情况,我们绝对没有理由继续缓存,因为旧缓存无论如何都属于不同的引用。

    这里的秘密是这样的:cache.clear() 应该在并且仅当引用确实与前一个不同时才会发生。

    !newDatabaseRef.getPath().toString().equal(oldPath)
    

    如果测试为真则:

     oldPath = newDatabaseRef.getPath().toString();
    

    然后:

    cache.clear();
    

    执行 chache.clear() 后,必须执行手动消耗以模拟 DB 回调。

    listener.accept(cache); //please de-reference
    

    并且必须在来自数据库的潜在 TRUE 回调到达之前完成此消耗(以防引用不为空)。

    请注意比赛条件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 2018-12-14
      • 2020-08-16
      • 2019-02-12
      相关资源
      最近更新 更多