【问题标题】:Why is my function returning before document/data retrieval from firestore is complete?为什么我的函数在从 firestore 检索文档/数据完成之前返回?
【发布时间】:2021-06-02 13:08:40
【问题描述】:

我正在尝试创建一个函数来检查用户名是否被使用或是否可用,我在 firestore 中的唯一方式是 UniqueID 是用户名而不是字段。这是函数:

private boolean checkUsernameValidity(String enteredUsername) {
    /**
     * Create code for querying through firestore DB for enteredUsername
     */
    final boolean[] usernameAvailable = {true};
    String USERTAG = "User documents";
    Log.d("Entered Username: ", enteredUsername);

    DocumentReference userDocRef = users.document(enteredUsername);

    userDocRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
            if (task.isSuccessful()) {
                DocumentSnapshot document = task.getResult();
                if (document.exists()) {
                    Log.d(USERTAG, "DocumentSnapshot data: " + document.getData());
                    Log.d("Warning", "Uh oh username is taken");
                    usernameAvailable[0] = false;
                    Toast.makeText(CreateAccount.this,
                            "This username is taken! Please enter a different username",
                            Toast.LENGTH_SHORT)
                            .show();
                } else {
                    Log.d(USERTAG, "No such document, This Username is available");
                }
            } else {
                Log.d(USERTAG, "get failed with ", task.getException());
            }
        }
    });

    /**
     * If there was a user with entered username found already;
     */

    if(!usernameAvailable[0]) {
        return false;
    }

    if (enteredUsername.length() < 5) {
        Toast.makeText(CreateAccount.this, "This username is too short",
                Toast.LENGTH_SHORT)
                .show();
        return false;
    }

    Log.d("Status", "All Good!");
    return true;
}

函数在usernameAvailable[0]改变前根据调试器返回true。图片在这里:

在图片中,成功状态的日志打印在表明用户名已被占用的日志之前。我猜该函数需要是异步的或类似的东西,但我不是 100% 创建异步方法。如何使我的函数检索文档(如果存在)并在获取文档函数中将我的 usernameAvailable[0] 设置为 false,然后再执行其余的 checkUsernameValidity 方法。

附: usernameAvailable 是一个最终的布尔数组,而不仅仅是一个布尔值,因为它是在内部类中访问的

【问题讨论】:

  • test 发表评论

标签: java android firebase android-studio google-cloud-firestore


【解决方案1】:

你说的是对的。您在DocumentReference 上进行的get() 调用在内部启动了一个异步任务,该任务将网络请求推迟到后台线程。如果不是这种情况,那么您将在收到结果所需的时间内拥有一个无响应的应用程序。因此,不是同步接收结果,而是在您的代码中附加一个 OnCompleteListener&lt;*&gt;,一旦请求完成,Firebase 会使用它来调用您的 onChanged 方法,以便您可以处理结果。

对于一个简单的解决方案,您可以在checkUsernameValidity 中实现某种回调,以处理您从任何地方调用的结果。实现看起来像这样:

interface Callback {

    void onResult(boolean valid);
}
void checkUsernameValidity(Callback callback) {

    userDocRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {

            callback.onResult(true);
        }
    });
}

我建议对异步性和回调的基本概念进行一些研究。

【讨论】:

  • 感谢您的回复,我的checkUsernameValidity 必须是无效的吗?我希望能够返回一个布尔值。
  • 您将无法同步返回 Firebase 调用的结果。正如我在回答中所说,get() 启动一个异步任务,您必须像我提到的那样实现一个回调系统,或者返回 Task 以由调用者处理。
  • 有道理。谢谢
  • @Iam 您的问题是否已得到解答,或者您还有什么不确定的地方吗?
  • 你已经回答了我的问题,我得到了它的工作。再次感谢
猜你喜欢
  • 2022-01-26
  • 2019-05-14
  • 1970-01-01
  • 2022-11-19
  • 2021-10-09
  • 1970-01-01
  • 2018-08-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多