【问题标题】:What is the reason that the code for "addOnSuccessListener" is being skipped? [closed]跳过“addOnSuccessListener”代码的原因是什么? [关闭]
【发布时间】:2022-01-25 17:33:42
【问题描述】:

我编写了一个函数,它应该获取用户 ID,访问 firestore 数据库中的所有用户属性,然后创建并返回对象。 但是该函数跳过了“addOnSuccessListener”的整个块,所以它返回一个空对象。

  public static Player getPlayer(String playerID) {

    final Player[] p = new Player[1];
    DocumentReference playerRef = fStore.collection("users").document(playerID);

    playerRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
        @Override
        public void onSuccess(DocumentSnapshot documentSnapshot) {
            if (documentSnapshot.exists()) {
                // getting all the attributes of the player from the database
                String age = documentSnapshot.getString("age");
                String city = documentSnapshot.getString("city");
                String email = documentSnapshot.getString("email");
                String fullName = documentSnapshot.getString("fullName");
                String gender = documentSnapshot.getString("gender");
                String nickName = documentSnapshot.getString("nickName");
                String password = documentSnapshot.getString("password");
                String phone = documentSnapshot.getString("phone");
                
                // creates a new player
                p[0] = new Player(fullName, nickName, email, password, phone, city, gender, age);
            } else {
                Toast.makeText(context.getApplicationContext(), "Player not found", Toast.LENGTH_LONG).show();
            }
        }
    })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Toast.makeText(context.getApplicationContext(), "Failed to fetch data", Toast.LENGTH_LONG).show();
                }
            });

    return p[0];
}

【问题讨论】:

  • 欢迎来到 Stack Overflow。请阅读How to Ask。不要发布代码或错误消息的图像,将相关代码复制/粘贴到您的问题中,并记住格式化为代码。
  • 数据从 Firestore(和大多数现代云 API)异步加载,这意味着您的 return p[0]p[0] = new Player... 执行之前运行。如果您在这些行上设置断点并在调试器中运行,或者在这些行之前添加日志记录,您可以很容易地看到这一点。解决方案总是一样的:任何需要 Firestore 数据的代码,必须在 onSuccess 内,从那里调用,或者以其他方式同步。见stackoverflow.com/a/48500679stackoverflow.com/a/51002413

标签: java android firebase google-cloud-firestore


【解决方案1】:

它会跳过它,因为OnSuccessListener 尚未运行它的回调。它不会运行,直到它有来自FireStore 的东西。您将立即返回尚未检索到的内容。

那么你如何解决它?您将需要某种回调功能。您可以使用RxJavaListenableFuture,也可以只重用OnSuccessListener 回调。

  public static void getPlayer(String playerID, OnSuccessListener<Player> listener ) {

    final Player[] p = new Player[1];
    DocumentReference playerRef = fStore.collection("users").document(playerID);

    playerRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
        @Override
        public void onSuccess(DocumentSnapshot documentSnapshot) {
            if (documentSnapshot.exists()) {
                // getting all the attributes of the player from the database
                String age = documentSnapshot.getString("age");
                String city = documentSnapshot.getString("city");
                String email = documentSnapshot.getString("email");
                String fullName = documentSnapshot.getString("fullName");
                String gender = documentSnapshot.getString("gender");
                String nickName = documentSnapshot.getString("nickName");
                String password = documentSnapshot.getString("password");
                String phone = documentSnapshot.getString("phone");
                
                // creates a new player
                p[0] = new Player(fullName, nickName, email, password, phone, city, gender, age); 
                //HERE
                //Send your player to your listener arg.
                listener.onSuccess(p[0]);
            } else {
                Toast.makeText(context.getApplicationContext(), "Player not found", Toast.LENGTH_LONG).show();
            }
        }
    })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Toast.makeText(context.getApplicationContext(), "Failed to fetch data", Toast.LENGTH_LONG).show();
                }
            });

      return;
  }

你现在怎么称呼getPlayer

 getPlayer("id",(player)->{
     player.doSomething();
     //HERE is your player received from FireStore
 });

【讨论】:

  • 感谢您的详细解释。所以我想现在我必须包装调用 getPlayer 函数的代码,因为它不会等到将玩家添加到数组列表中,所以我得到一个空列表。
  • 为了将来的参考,您检索到的任何非硬编码的东西,很可能需要像上面那样以异步方式处理。访问文件、数据库和云服务中的数据都可能需要比MainLopper 分配的更多时间,也就是说,您不能只是等待。
猜你喜欢
  • 1970-01-01
  • 2011-01-11
  • 2013-10-18
  • 1970-01-01
  • 2016-09-25
  • 2020-04-12
  • 2014-10-17
  • 2021-09-14
  • 2019-12-01
相关资源
最近更新 更多