Firebase ValueEventListener onDataChange()未被调用

时间:2017-10-30 07:46:22

标签: java android firebase-realtime-database

我已将我的代码跟踪到崩溃的根本原因,显然这个构造函数无法更新类的变量。当我试图从这个类中获取数据时,我得到空指针异常。您可以安全地假设记录已经存在于数据库中,它所要做的就是获取数据并将其放在类/对象中。我现在只想获得名称,因为我正在测试该对象是否仍然为空。

Database structure

class Saver{
    private String name;
// constructor of Saver class
public Saver(final String uid) {
        Log.d("Saver.java","Reached here"); // this works
        FirebaseDatabase.getInstance().getReference().addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(final DataSnapshot dataSnapshot) {
                Log.d("Saver.java", "OnDataChange"); // does not work
                if(dataSnapshot.hasChild("users/" + uid)){
                    LoadRecord(dataSnapshot, uid);
                }
                else{
                    // set a new record into the database
                    FirebaseDatabase.getInstance().getReference().child("users/" + uid).setValue(CreateNewRecord(FirebaseAuth.getInstance().getCurrentUser())).addOnCompleteListener(new OnCompleteListener<Void>() {
                        @Override
                        public void onComplete(@NonNull Task<Void> task) {
                            if(task.isSuccessful()){
                                LoadRecord(dataSnapshot, uid);
                            }
                            else{
                                Log.e("Saver.java","Failed to set record in database");
                            }
                        }
                    });
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                  Log.e("LifeSaver.java","Error: " + databaseError.getMessage());
            }
        });
    }

// This function loads the data into the object
private void LoadRecord(DataSnapshot dataSnapshot, String uid){
        Log.d("LifeSaver.java","Uid:"+uid);
        // load the existing record in the database
        Saver temp = dataSnapshot.child("users/" + uid).getValue(Saver.class);
        setName(temp.getName());
    }
}
public void setName(String name) {
    this.name = name;
}
private Saver CreateNewRecord(FirebaseUser firebaseUser){
    Saver saver = new Saver ();
    saver.setName(firebaseUser.getDisplayName());
    Log.d("saver","saver name: " + saver.getName());
    return continuLifeUser;
}

显然,在数据库发生变化之前,onDataChange函数不会运行。

  1. 如果可能,我该如何手动触发此功能?
  2. 我应该拥有一个拥有此节点子节点的DataSnapshot吗?如果是这样,怎么样? (请显示代码,以便我可以看到您正在解释的内容)
  3. 有更好的方法吗?
  4. 编辑1: 这是构造函数中应该调用FirebaseDatabase的logcat语句:

    D/Saver.java: Reached here with hA4hZrBieISwMOZaMYe7m6K5tpI3
    I/DynamiteModule: Considering local module com.google.android.gms.firebase_database:4 and remote module com.google.android.gms.firebase_database:6
    I/DynamiteModule: Selected remote version of com.google.android.gms.firebase_database, version >= 6
    I/art: DexFile_isDexOptNeeded failed to open oat file '/data/dalvik-cache/x86_64/data@data@com.google.android.gms@app_chimera@m@00000004@DynamiteModulesC_GmsCore_prodlmp_alldpi_release.apk@classes.dex' for file location '/data/data/com.google.android.gms/app_chimera/m/00000004/DynamiteModulesC_GmsCore_prodlmp_alldpi_release.apk': Failed to open oat filename for reading: No such file or directory
    D/Saver.java: Ended here
    D/LoginAct.java: Name: null
    

3 个答案:

答案 0 :(得分:1)

我通过加载屏幕解决了这个问题。我应该记得这个调用是Async,它需要一个接收器来调用放置数据的函数,然后再进行下一个活动。

private interface OnGetDataListener {
    void onSuccess(DataSnapshot dataSnapshot);
    void onFailure();
}

这是一个小型代码,供您在调用数据库获取数据时必须实现的侦听器。您可以查看与此类似的其他帖子。

答案 1 :(得分:0)

首先,您应该将数据添加到数据库,然后才能使用它。看起来Firebase中没有可用的数据。只需在firebase数据库中添加一个键值对,然后就会触发它。

FirebaseDatabase.getInstance().getReference().child("users/" + uid).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(final DataSnapshot dataSnapshot) {
            Log.d("Saver.java", "OnDataChange"); // does not work
            if(dataSnapshot!=null){
                LoadRecord(dataSnapshot);
            }
            else{
                // set a new record into the database
                FirebaseDatabase.getInstance().getReference().child("users/" + uid).setValue(CreateNewRecord(FirebaseAuth.getInstance().getCurrentUser())).addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        if(task.isSuccessful()){
                            LoadRecord(dataSnapshot);
                        }
                        else{
                            Log.e("Saver.java","Failed to set record in database");
                        }
                    }
                });
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
              Log.e("LifeSaver.java","Error: " + databaseError.getMessage());
        }
    });
}
   // Load record should be like this...
   private void LoadRecord(DataSnapshot dataSnapshot){
    Log.d("LifeSaver.java","Uid:"+uid);
    // load the existing record in the database
    Saver temp = dataSnapshot.getValue(Saver.class);
    setName(temp.getName());
}

}

答案 2 :(得分:0)

要获取users节点下所有用户的所有名称,请使用以下代码:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = rootRef.child("users");
ValueEventListener eventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String name = ds.child("name").getValue(String.class);
            Log.d("TAG", name);
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
usersRef.addListenerForSingleValueEvent(eventListener);

输出将是:

Michael Ong
//other names

如果您只想获取特定用户的名称,请使用以下代码:

FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
String uid = firebaseUser.getUid();

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("users").child(uid);
ValueEventListener eventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        String name = dataSnapshot.child("name").getValue(String.class);
        Log.d("TAG", name);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
uidRef.addListenerForSingleValueEvent(eventListener);

输出只是一条记录:

Michael Ong