您所看到的很可能是Firebase数据被异步加载的事实.第一次遇到这种情况时,这是一个巨大的范式转变.但是,由于大多数现代云API都以这种方式工作,因此最好尽快将其接受.
我发现在放置一些日志记录语句时会看到什么的最简单方法:
System.out.println("Before adding listener");
mRefReg.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("In onDataChange");
}
public void onCancelled(DatabaseError databaseError) { }
});
System.out.println("After adding listener");
与您的直觉告诉您的相反,此输出将是:
Before adding listener
After adding listener
In onDataChange
这样做的原因是(正如我一开始所说的)Firebase从数据库异步获取数据.实现此目的的一种有趣方法是更改??数据(例如,在Firebase Database console中).当您进行更改时,onDataChange将再次被调用并打印另一个:
In onDataChange
不幸的是,这意味着您无法执行以下操作来处理子计数:
int count = -1;
System.out.println("Before adding listener, count="+count);
mRefReg.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
count = dataSnapshot.getChildrenCount();
System.out.println("In onDataChange, count="+count);
}
public void onCancelled(DatabaseError databaseError) { }
});
System.out.println("After adding listener, count="+count);
因为输出将是:
Before adding listener: count=-1
After adding listener: count=-1
In onDataChange: count=3 (assuming you have 3 children)
我发现处理这种异步加载的最佳技巧是重新构造问题.与其说“首先获得计数,然后用它做xyz”,不如将其定为“只要获得计数,就用xyz”.这意味着您需要将需要计数的代码移到onDataChange()中:
mRefReg.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
int count = dataSnapshot.getChildrenCount();
// TODO: show the count in the UI
}
public void onCancelled(DatabaseError databaseError) { }
});
如果以这种方式实现,则只要数据库中的项目数发生更改,UI中的计数就会更新.