Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从Firebase数据库高效获取用户数据_Java_Android_Firebase_Firebase Realtime Database - Fatal编程技术网

Java 从Firebase数据库高效获取用户数据

Java 从Firebase数据库高效获取用户数据,java,android,firebase,firebase-realtime-database,Java,Android,Firebase,Firebase Realtime Database,我试图访问要显示在屏幕上的用户用户名,并从Firebase数据库检索用户名 获取用户名的代码有点长 myRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { String userName = dataSnapshot.child("userN

我试图访问要显示在屏幕上的用户用户名,并从Firebase数据库检索用户名

获取用户名的代码有点长

myRef.addListenerForSingleValueEvent(new ValueEventListener() {

        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String userName = dataSnapshot.child("userName").getValue(String.class);
            navUsername.setText(userName);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            throw databaseError.toException();
        }
    });
因此,我试图使代码返回一个名为“specUserName”的字符串,这样我就可以轻松地从任何类访问它,而不必每次都输入那么长的代码字符串。在我的User.class中,我添加了这个

    public String getUserName() {
    myRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            specUserName = dataSnapshot.child("userName").getValue(String.class);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            throw databaseError.toException();
        }
    });
    return specUserName;
}
我正试图通过这样做在我的HomePage.class中检索它

    users.getUserName();
    navUsername.setText(users.specUserName);
但是现在每当我打开主页时,它总是崩溃,这就是我在日志中收到的错误

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.brent.fifty_fifty.User.getUserName()' on a null object reference
    at com.example.brent.fifty_fifty.HomePage.onCreateOptionsMenu(HomePage.java:84)
HomePage:84是我调用getUserName()方法的地方,但它总是返回null并崩溃


有什么帮助吗?

数据是从Firebase异步加载的。因为你不能让
getUserName
等待数据可用(这意味着你的应用程序没有响应),所以你无法像那样返回用户名

要了解原因,请放置以下几条日志语句:

System.out.println("Before attaching listener");
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        System.out.println("Got data");
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        throw databaseError.toException();
    }
});
System.out.println("After attaching listener");
运行此代码时,它会打印:

在附加侦听器之前

附加侦听器后

得到数据

这可能不是你所期望的。但它明确地解释了为什么不能返回用户名。执行
return
语句时,数据尚未加载,并且
onDataChange()
尚未调用

有两种常见的解决方法:

  • 将需要用户名的代码移动到
    getUserName
    方法中。这是迄今为止最简单的方法,但会降低
    getUserName
    方法的可重用性
  • 创建一个回调接口,将其传递到
    getUserName
    ,然后在加载用户名时调用该接口。这与Firebase本身的
    ValueEventListener.onDataChange
    类似,但特定于应用程序逻辑
  • 我建议您在我的回答中查看以下内容,而不是在此处显示两者的代码:

    为了证明你不是唯一一个挣扎于此的人,这里有一些关于这个话题的问题:


    这可能是由于各种原因造成的,其中一个原因可能是
    myRef
    没有在用户类中正确引用您的数据库或其他任何原因

    但是,您必须获得用户名的问题可以通过多种方式解决

    首先,如果您正在使用电子邮件/密码注册用户,那么您已经拥有他们在GoogleID中拥有的
    用户
    的用户名

    您可以通过以下代码轻松获得
    用户名

    FirebaseAuth-mAuth=FirebaseAuth.getInstance();
    字符串username=mAuth.getCurrentUser.getUsername();
    
    此外,如果您在一个活动中有数据,则可以很容易地将数据传递到下一个活动。您可以使用
    putExtra()
    方法执行此操作

    //从第一次获取用户名值的类向MainActivity发送数据
    Intent Intent=new Intent(getBaseContext(),MainActivity.class);
    intent.putExtra(“用户名”,用户名);
    星触觉(意向);
    //接收MainActivity中的数据
    字符串uname=getIntent().getStringExtra(“用户名”);
    
    你好,弗兰克,这真的让我非常接近解决我的问题,所以非常感谢。我已经看过了你发来的关于这个问题的其他一些例子,并且已经解决了一些问题。我已经准备好回调并设置好了所有内容,但我正在努力弄清楚到底要调用什么来检索“public void getUser(final MyCallback callback)”生成的字符串。我在需要的地方正确地调用该方法,将其命名为“getUser(new MyCallback…),但我正在尝试更新UI以显示正在检索的人员用户名,我应该放置什么变量来将我的一个TextView设置为“public void getUser”生成的字符串?抱歉,如果评论中有点混乱-如果你不明白我在问什么,我可以尝试提供更多信息。很高兴听到你取得了进步。我不确定我是否理解这个新问题,但这可能是因为缺乏背景。与其描述你所拥有的,不如展示你所拥有的。在这一点上,发布一个新的问题可能会更好,因为注释中的代码很难在单个语句之外阅读。