Android 了解Firebase上的childEventListener是否已完成加载所有数据
我正在使用Firebase实时数据库为我的Android应用程序存储和检索数据。在我的活动中,我使用Android 了解Firebase上的childEventListener是否已完成加载所有数据,android,firebase,firebase-realtime-database,Android,Firebase,Firebase Realtime Database,我正在使用Firebase实时数据库为我的Android应用程序存储和检索数据。在我的活动中,我使用childEventListener从Firebase检索所有数据(例如:用户数据列表) 我想显示一个进度条,只要数据没有完全从数据库中检索到。如何检查是否已完全检索所有数据,以便在加载数据后关闭进度条?有一种常见的方法可以检测Firebase何时在给定位置同步初始数据。此方法使用以下方法之一: 值事件始终在最后触发,并保证包含快照拍摄之前发生的任何其他事件的更新 因此,如果给定位置上同时有一个V
childEventListener
从Firebase检索所有数据(例如:用户数据列表)
我想显示一个进度条,只要数据没有完全从数据库中检索到。如何检查是否已完全检索所有数据,以便在加载数据后关闭进度条?有一种常见的方法可以检测Firebase何时在给定位置同步初始数据。此方法使用以下方法之一: 值事件始终在最后触发,并保证包含快照拍摄之前发生的任何其他事件的更新 因此,如果给定位置上同时有一个
ValueEventListener
和一个ChildEventListener
,则保证在所有onchildaded()
调用完成后调用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不只是加载数据。它不断地将数据从服务器同步到所有连接的客户端。因此,实际上没有任何时刻可以完全检索到数据。我用非常简单的方法完成了这项工作。我让一个int计数,然后每当它进入函数时,我递增它并检查它是否等于child的总数。如果它相等,那么可以停止进度条
int count = 0;
ref.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
count++;
if(count >= dataSnapshot.getChildrenCount()){
//stop progress bar here
}
}
使用
听起来很奇怪。我刚刚添加了一个新项,只得到了:
在-K4uCQDYR0k05Xqyj6jI之后添加-K6ns123jl6xQXfQJR\u r到UI(如果您仍然体验到这种行为)(并且确定您只使用addListenerForSingleValueEvent()添加侦听器)
,打开一个新问题,并包含重现问题所需的最少代码。如果您能在onDataChange()
中执行dataSnapshot.parent().getChildrenCount()
操作,那就太好了。我假设使用addListenerForSingleValueEvent()
来获取项目数,将加载所有数据(刚刚加载到onDataChange()
)中的内容?Rem:如果客户端缓存(android设备)中已有某些项,则此解决方案似乎不起作用。在这种情况下,onDataChange()事件在ChildEventListener完成同步服务器上的所有子项之前从缓存中检索元素!!这仅适用于第一次。缓存数据时onDataChange()调用First,但不会ChildEventListener
获取所有子项,而不仅仅是添加的子项?因此,您将有两个重复集,一个来自SingleValueEventListener
,另一个来自ChildEventListener
。我的英语有点弱:以后如何摆脱listener?或者我们不必这样做抱歉,回复太晚了…:当您不需要侦听器时,您必须始终删除它们。您不应该删除的唯一侦听器是addListenerForSingleValueEvent(),它在事件触发时自动删除,但getChildrenCount()返回此查询的子项计数或节点的子项计数?因为如果是第二个,如果有筛选器,此方法将给出错误的答案。
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) {
}
});