我希望将Firebase数据库中的子项数存储到Android Studio中的变量中。我试图获取Firebase中2个不同子节点下的所有节点的总数,但它返回java.lang.ArithmeticException:除以零。任何帮助将不胜感激。
private long absent, present, total, attendanceRecord;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_student_stats);
statsResult = (TextView) findViewById(R.id.statsResult);
ValueEventListener eventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
String name = ds.getKey();
String selectedClass;
Bundle extras = getIntent().getExtras();
if (extras == null) {
selectedClass = null;
} else {
selectedClass = extras.getString("classSelected");
}
absentNumber = FirebaseDatabase.getInstance().getReference().child("Users").child(user.getUid()).child("Classes").child(selectedClass).child("AbsentStudents").child(name);
presentNumber = FirebaseDatabase.getInstance().getReference().child("Users").child(user.getUid()).child("Classes").child(selectedClass).child("PresentStudents").child(name);
presentNumber.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snap: dataSnapshot.getChildren()) {
present = snap.getChildrenCount() ;
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
absentNumber.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snap: dataSnapshot.getChildren()) {
absent = snap.getChildrenCount() ;
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
total = present + absent;
attendanceRecord = present / total;
allStudentsList.add(name + "\t" + attendanceRecord + "%");
}
答案 0 :(得分:0)
问题是数据是从Firebase异步加载的,当您运行除法时数据尚未加载(因此total
为0
)。要了解异步加载的工作原理,让我们在代码中添加一些简单的日志记录:
System.out.println("Before attaching listener");
presentNumber.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("Got data");
}
@Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
System.out.println("After attaching listener");
运行此代码时,您将获得:
在附加监听器之前
附加监听器后
获得数据
这可能不是你预期的顺序。因为从Firebase服务器获取数据需要一些时间,所以主代码会继续(并运行“After”日志)。只有从Firebase获得数据后,您的onDataChange
才会被调用。
了解这一点,我希望错误更有意义:当您运行attendanceRecord = present / total
时,total
仍然是0
,因为数据尚未加载。< / p>
处理异步加载的解决方案是重新构建您的问题。现在你的代码说:“首先加载A,然后加载B,然后用A和B做一些事情”。相反,我觉得将其框架化为有用:“首先开始加载A和B.一旦加载A和B,就用它们做点什么。”在您的代码中,这将转换为添加额外的功能:
public void checkAttendanceRecord(long present, long absent) {
if (present >= 0 && absent >= 0) {
total = present + absent;
attendanceRecord = present / total;
allStudentsList.add(name + "\t" + attendanceRecord + "%");
}
}
然后
long present = -1;
long absent = -1;
presentNumber.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snap: dataSnapshot.getChildren()) {
present = snap.getChildrenCount() ;
}
checkAttendanceRecord(present, absent);
}
@Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
absentNumber.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snap: dataSnapshot.getChildren()) {
absent = snap.getChildrenCount() ;
}
checkAttendanceRecord(present, absent);
}
@Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
请注意,我不确定onDataChange
中的循环是什么,所以我按原样保留它们,并只关注代码的异步性质。
要了解有关异步数据加载的更多信息,请查看: