Firebase检索数据Null外部方法

时间:2016-11-06 07:41:15

标签: android firebase firebase-realtime-database

我将以下方法放在onCreate()内,当应用启动它时会触发此方法。但是,当我尝试将mName移到ValueEventListener()之外时,它会返回null并且应用程序崩溃了。

任何人都知道为什么会出现这个问题?

 ValueEventListener postListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            UserDetails info = dataSnapshot.getValue(UserDetails.class);
            Log.d(TAG, String.valueOf(dataSnapshot));

            mName = info.getName();
            **Log.d(TAG, mName); // HERE GET THE NAME**

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.w(TAG, "getUser:onCancelled", databaseError.toException());
        }
    };
    mDatabase.child("Admin")
            .child("Info")
            .child(uid)
            .addValueEventListener(postListener);

    **Log.d(TAG, mName); // HERE GET NULL**

2 个答案:

答案 0 :(得分:2)

正如其他人所说:来自Firebase数据库的所有数据都是异步读取的。通过在代码中添加更多日志语句来最简单地看到这一点:

Log.d(TAG, "Before attaching listener");
mDatabase.child("Admin")
        .child("Info")
        .child(uid)
        .addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        Log.d(TAG, "In listener's onDataChange");
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.w(TAG, "getUser:onCancelled", databaseError.toException());
    }
});
Log.d(TAG, "After attaching listener");

与您的预期不同,其输出为:

  

在附加监听器之前

     

附加监听器后

     

内部侦听器的onDataChange

处理异步行为的方法是重新构建您的问题。

现在您的代码已经编写:首先我们加载数据,然后我们记录它。

如果您将问题重新解析为:“无论何时加载数据,我们都会记录它”,您将得到如下代码:

mDatabase.child("Admin")
        .child("Info")
        .child(uid)
        .addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        UserDetails info = dataSnapshot.getValue(UserDetails.class);
        Log.d(TAG, String.valueOf(dataSnapshot));

        mName = info.getName();
        Log.d(TAG, mName);

    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.w(TAG, "getUser:onCancelled", databaseError.toException());
    }
});

所以需要数据的所有代码都需要在onDataChange()内。或者,您可以创建自己的自定义回调方法,并从onDataChange()调用该方法。但逻辑始终是相同的:需要数据的代码在数据可用时从onDataChange() 触发

答案 1 :(得分:1)

这是因为Firebase在您执行此操作时仍然无法检索数据:

Log.d(TAG, mName);

mName目前为空,因为此行已在Firebase获取数据之前执行。

要解决此问题,您必须Log.d(TAG, mName) 内部 onDataChange方法。否则,它将是null,因为您尚未设置该值(因为Firebase仍然没有获得该值)。