我正在使用Firebase作为我的Android应用程序的数据库。我需要查看数据库中所有人的三元组并为每个组分配一个分数,这样我才能找到得分最高的组。所以我想到的是像这样的伪代码:
for person1 in People {
for person2 in People{
for person3 in People{
if(calculateScore(person1, person2, person3)>score){
score = calculateScore(person1, person2, person3);
}
}
}
}
所以我的代码是这样的:
peopleRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot1 : dataSnapshot.getChildren()) {
Log.d("TAG", "1st loop");
peopleRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot2 : dataSnapshot.getChildren()) {
Log.d("TAG", "2nd loop");
peopleRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot3 : dataSnapshot.getChildren()) {
Log.d("TAG", "3rd loop");
int score = calculateScore(childDataSnapshot1, childDataSnapshot2, childDataSnapshot3);
if(score > bestScore){
bestScore = score;
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
}
问题是,执行的顺序混乱了。我希望它像1 2 333333333 2 333333333 2 33333333 1 2 33333333 2 333333 ...但它打印的东西像1111 2222222222222 33333333 ...
我知道Firebase是异步的,但我认为它应该可以工作,因为我以嵌套的方式调用onDataChange中的所有内容。我怎么解决这个问题?
ValueEventListener()
返回任何数据库引用节点下的所有数据。因此,递归地在同一节点上调用同一个侦听器是没用的。
加载完所有数据后,您可以使用for循环存储所有对象并在内存中进行比较。
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
// parse person snapshot
// add to list
}
// then compare with for loop
// int score = calculateScore(person1, person2, person3);
从Firebase数据库获取数据时使用嵌套循环并不能保证您获得循环顺序的结果。发生这种情况是因为循环中的每个onDataChange()
方法都有其异步行为,因此嵌套那些循环并不能解决执行的顺序。
不幸的是,您无法知道何时从数据库中获取数据以便调用第二个循环。这是因为Firebase是一个实时数据库,并且获取数据可能永远不会完成。这就是为什么命名为实时数据库,因为在任何momemnt中都可以更改数据库,可以添加或删除项目。