我有一个方法应该初始化我的字段变量currentTask
。我不明白为什么我无法从firebase读取我的对象。这是方法:
private void getCurrentTask() {
final DatabaseReference dRef1 = database.getReference().child("Users").child(uid).child("CurrentTask");
dRef1.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
currentTask = dataSnapshot.getValue(CurrentTask.class);
} else {
Toast toast = Toast.makeText(TasksListActivity.this, "no magic", Toast.LENGTH_LONG);
toast.show();
}
}
@Override
public void onCancelled(DatabaseError databaseError) {}
});
if (currentTask == null) {
Toast toast = Toast.makeText(this, "magic)", Toast.LENGTH_LONG);
toast.show();
}
}
Toast no magic
永远不会出现,因此对象存在。但是,在方法结束时出现了to magic
,这意味着currentTask == null
。即使在初始化之后
这是我的数据库:
答案 0 :(得分:4)
@Roasario和@ReazMurshed的回答是正确的。但是,让我通过描述您的代码如何不按预期工作来使其变得更简单:
private void getCurrentTask() {
...
dRef1.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
... (point 1)
}
@Override
public void onCancelled(DatabaseError databaseError) {}
});
... (point 2)
}
Firebase数据库异步加载您的数据。这意味着(简单地说)获取数据的过程不会干扰您的主要过程。考虑到这一点,(point 2)
中的代码并不总是在(point 1)
中的代码之后执行,反之亦然。虽然(point 1)
中的代码通常会在(point 2)
之后执行,但并不总是如此。因此,您应该考虑在(point 1)
中编写的代码可以随时执行。
然后你应该用这个概念编写你的代码。这意味着如果你想对(point 1)
内的变量做任何事情(比如用dataSnapshot值填充currentTask然后检查它是否为null),你应该将它全部放在(point 1)
希望得到这个帮助。
答案 1 :(得分:2)
请注意,onDataChange是异步的,因此if语句将始终返回false,因为您在之前未读取数据时检查它是否为null。您应该检查onDataChange中是否为null(以确保已读取数据),如下所示:
private void getCurrentTask() {
final DatabaseReference dRef1 = database.getReference().child("Users").child(uid).child("CurrentTask");
dRef1.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
currentTask = dataSnapshot.getValue(CurrentTask.class);
if (currentTask == null) {
Toast toast = Toast.makeText(this, "magic)", Toast.LENGTH_LONG);
toast.show();
}
} else {
Toast toast = Toast.makeText(TasksListActivity.this, "no magic", Toast.LENGTH_LONG);
toast.show();
}
}
@Override
public void onCancelled(DatabaseError databaseError) {}
});
}
答案 2 :(得分:2)
修改您的参考网址有点像这样。
final DatabaseReference dRef1 = database.getReference().child("Users").child(uid);
现在创建一个类来表示每个节点。
public class User {
public UserCharacter Character;
public UserCurrentTask CurrentTask;
public String Email;
public UserTasks Tasks;
}
现在在onDataChange
内你需要这样做。
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
User mUser = dataSnapshot.getValue(User.class);
currentTask = mUser.CurrentTask;
} else {
// Show toast or something.
}
}
正如@Roasario所说,onDataChanged
函数是Async
。因此,在检查null
值时,您无法获得实际值。