Firebase阅读问题。对象始终为null

时间:2017-01-06 11:20:05

标签: java android firebase firebase-realtime-database

我有一个方法应该初始化我的字段变量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。即使在初始化之后

这是我的数据库:

enter image description here

3 个答案:

答案 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值时,您无法获得实际值。