【问题标题】:Find out if childEventListener on Firebase has completed loading all data查看 Firebase 上的 childEventListener 是否已完成所有数据的加载
【发布时间】:2016-04-04 11:44:54
【问题描述】:

我正在使用 Firebase 实时数据库为我的 Android 应用程序存储和检索数据。在我的活动中,我使用 childEventListener 从 Firebase 检索所有数据(例如:用户数据列表)。

只要数据没有从数据库中完全检索到,我想显示一个进度条。如何检查所有数据是否已完全检索,以便在数据加载后关闭进度条?

【问题讨论】:

    标签: android firebase firebase-realtime-database


    【解决方案1】:

    有一种常用方法可以检测 Firebase 何时完成对给定位置上的初始数据的同步。这种方法利用了Firebase event guarantees 之一:

    值事件总是最后触发,并保证包含在拍摄快照之前发生的任何其他事件的更新。

    因此,如果您在给定位置同时拥有ValueEventListenerChildEventListener,则保证在所有onChildAdded() 调用发生后调用ValueEventListener.onDataChange()。您可以使用它来了解初始数据加载何时完成:

    ref.addListenerForSingleValueEvent(new ValueEventListener() {
        public void onDataChange(DataSnapshot dataSnapshot) {
            System.out.println("We're done loading the initial "+dataSnapshot.getChildrenCount()+" items");
        }
        public void onCancelled(FirebaseError firebaseError) { }
    });
    ref.addChildEventListener(new ChildEventListener() {
        public void onChildAdded(DataSnapshot dataSnapshot, String previousKey) {
            System.out.println("Add "+dataSnapshot.getKey()+" to UI after "+previousKey);
        }
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
        }
        public void onChildRemoved(DataSnapshot dataSnapshot) {
        }
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {
        }
        public void onCancelled(FirebaseError firebaseError) { }
    });
    

    在我的测试运行中,结果如下:

    Add -K2WLjgH0es40OGWp6Ln to UI after null
    Add -K2YyDkM4lUotI12OnOs to UI after -K2WLjgH0es40OGWp6Ln
    Add -K2YyG4ScQMuRDoFogA9 to UI after -K2YyDkM4lUotI12OnOs
    ...
    Add -K4BPqs_cdj5SwARoluP to UI after -K4A0zkyITWOrxI9-2On
    Add -K4BaozoJDUsDP_X2sUu to UI after -K4BPqs_cdj5SwARoluP
    Add -K4uCQDYR0k05Xqyj6jI to UI after -K4BaozoJDUsDP_X2sUu
    We're done loading the initial 121 items
    

    因此您可以使用onDataChanged() 事件来隐藏进度条。

    但要记住一件事:Firebase 不只是加载数据。它不断地将数据从服务器同步到所有连接的客户端。因此,实际上没有任何时刻可以完全检索到数据。

    【讨论】:

    • 这听起来很奇怪。我刚刚添加了一个新项目并且只得到了:Add -K6ns123jl6xQXfQJR_r to UI after -K4uCQDYR0k05Xqyj6jI 如果您仍然遇到这种行为(并且确定您只添加了带有addListenerForSingleValueEvent() 的侦听器,请打开一个新问题并包含重现您的问题所需的最少代码。请参阅@ 987654322@
    • 如果你能在onDataChange() 中做dataSnapshot.parent().getChildrenCount(),那就太好了。我假设使用addListenerForSingleValueEvent() 获取项目数,将加载所有数据(刚刚加载到onDataChange()再次
    • Rem :如果某些项目已经在客户端缓存(Android 设备)中,此解决方案似乎不起作用。在这种情况下,onDataChange() 事件会在 ChildEventListener 完成之前从缓存中检索元素以从服务器同步所有子节点!
    • 这仅适用于第一次。缓存数据时首先调用 onDataChange()
    • 但是ChildEventListener 不会获取所有子节点,而不仅仅是添加的子节点吗?那么你有 2 个重复的集合,一个来自 SingleValueEventListener,另一个来自 ChildEventListener
    【解决方案2】:

    我以非常简单的方式完成了它。我让一个 int 计数,然后每次当它进入函数时,我都会增加它并检查它是否等于孩子的总数。如果相等,那么您可以停止进度条

        int count = 0;    
        ref.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                count++;
    
    
                if(count >= dataSnapshot.getChildrenCount()){
                    //stop progress bar here
                }
            }
    

    【讨论】:

    • 我的英语有点弱:D
    • 之后你如何摆脱监听器?还是我们不必担心?
    • 很抱歉回复晚了... :D
    • 当您不需要侦听器时,您必须始终删除它们。唯一不应该删除它的监听器是 addListenerForSingleValueEvent(),它会在事件触发时自动删除
    • 但是 getChildrenCount() 返回这个查询的孩子数还是节点的孩子数?因为如果是第二个,如果有过滤器,这个方法会给出错误的答案。
    【解决方案3】:

    使用

      totalChilds = 0; 
      ref..addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                        totalChilds = dataSnapshot.getChildrenCount();
                        ref.addChildEventListener(new ChildEventListener() {
                               @Override
                               public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
                               count++;
                               if(count >= totalChilds){
                                     progressDialog.dismiss();
                }
                @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
    
            }
    
            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
    
            }
    
            @Override
            public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
    
            }
    
            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
    
            }
        });
    
                    }
    
                    @Override
                    public void onCancelled(@NonNull DatabaseError databaseError) {
    
                    }
                });
    

    【讨论】:

      猜你喜欢
      • 2012-01-07
      • 2011-10-18
      • 2012-04-03
      • 1970-01-01
      • 2018-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多