【问题标题】:Android - firestore query not finishing before return statement [duplicate]Android - 在返回语句之前未完成 Firestore 查询 [重复]
【发布时间】:2019-03-07 20:50:50
【问题描述】:

所以我遇到的问题是 loadUserNameFromFirestore() 方法在 firestore db.collection.get() 查询完成执行之前执行 return 语句。我在 firestore db.collection.get() 查询之后和方法返回语句之前放置了日志。

private String loadUserNameFromFirestore(Appointment appointment) {

    final StringBuilder userFullName = new StringBuilder();
    String userUid = appointment.getAppointment_doctor_uid();

    db.collection(Constants.FIRESTORE_DOCTOR).document(userUid)
            .get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
            DocumentSnapshot documentSnapshot = task.getResult();
            userFullName.append(documentSnapshot.getString(Constants.FIRESTORE_STAFF_TITLE)).append(" ");
            userFullName.append(documentSnapshot.getString(Constants.FIRESTORE_STAFF_FNAME)).append(" ");
            userFullName.append(documentSnapshot.getString(Constants.FIRESTORE_STAFF_LNAME));
            Log.d("DEBUG_APP", userFullName.toString());
        }
    })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                }
            });

    Log.d("DEBUG_APP", "Final: " + userFullName.toString());

    return userFullName.toString();
}

以下是根据上述代码创建的日志。

10-03 02:43:30.561....: Final:  
10-03 02:43:31.044....: Dr Naila Alam

如上所示,return 语句“First:”之前的日志首先执行,然后是 firestore 查询之后的日志“Dr Naila Alam”。

有没有办法确保在 firestore 完成执行之前不会调用 return 语句。非常感谢任何帮助。

【问题讨论】:

  • 您现在无法返回尚未加载的内容。因此,请检查副本以了解您为什么会出现这种行为以及如何使用自定义回调来解决此问题。
  • 抱歉,我没有看到副本。这确实有效!谢谢!但是,当我在 OnClick 方法中调用回调时,我无法使用 intent.putExtra(callBackData) 将数据放入意图中。在将数据放入意图之前,将首先调用 startActivity(),因此我不会在第二个活动中看到回调数据。 @AlexMamo
  • 很高兴听到它有效:) 这似乎是另一个问题。为了遵守本社区的规则,请再次提出新问题,以便我和其他用户可以帮助您。
  • 没问题,谢谢

标签: java android firebase google-cloud-firestore


【解决方案1】:

如您所见,您对 firebase 的请求是一个异步操作,因此代码无需等待它完成而是继续他的路线。 您附加的侦听器在另一个线程上工作,因此您的 GUI 不会冻结。这就是为什么您不能运行通过 firebase 调用返回值的方法。

您必须修改您的代码以调用方法来检索值,并在 onComplete 方法中调用另一个方法来设置获取的值。

例如:(假设您需要用户名在 GUI 上显示)

public void setTextUsername(String username)
    this.textViewUsername.setText(username);
    //here you can do all you need with username value
}

public void loadUserNameFromFirestore(Appointment appointment){
    String userUid = appointment.getAppointment_doctor_uid();

    db.collection(Constants.FIRESTORE_DOCTOR).document(userUid)
        .get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {

    @Override
    public void onSuccess(@NonNull Task<DocumentSnapshot> task) {
        StringBuilder userFullName = new StringBuilder();
        DocumentSnapshot documentSnapshot = task.getResult();
        userFullName.append(documentSnapshot.getString(Constants.FIRESTORE_STAFF_TITLE)).append(" ");
        userFullName.append(documentSnapshot.getString(Constants.FIRESTORE_STAFF_FNAME)).append(" ");
        userFullName.append(documentSnapshot.getString(Constants.FIRESTORE_STAFF_LNAME));
        Log.d("DEBUG_APP", userFullName.toString());
        setTextUsername(userFullName.toString());
    }})
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
            }
        });
}

如果您有不清楚的地方,请随时提问。我很乐意提供帮助!

【讨论】:

  • 谢谢!!这真的很有帮助。虽然,我在我的 RecyclerView 适配器的 onBindViewHolder() 中使用 loadUserNameFromFirestore() 方法。因此,使用您的解决方案,holder.setText() 最终会在 loadUserNameFromFirestore() 之前被首先调用。这将导致 setTextUsername() 不被调用,因此不起作用。我解决这个问题的方法是通过 ViewHolder 作为 loadUserNameFromFirestore() 中的参数,并在 setTextUsername() 中调用 holder.setText()。但是,这将不允许我在 OnClick() 中检索用户名。有没有办法解决这个问题?
  • 对不起,但我不明白你的意思.. 这是一个非常糟糕的使用 firebase 的技术。如果我理解正确,您为回收视图中的每个项目调用 READ 操作..这意味着如果您有 200 个约会,您对 firebase 进行 201 个读取调用(约会列表 1 个,每个用户 200 个).. 这是对表演和金钱都非常不利 xD 如果您只需要用户名,请考虑将其作为约会字段.. 所以,检索约会列表,您也有用户名!
  • 为了更多的理解,例如你在firebase中的约会结构将是:约会{ askdmadnbwKNSA { id: askdmadnbwKNSA , userId: LIKs854Aend , userName: Doc.Michael , date:1929281182912 等...}
  • 是的,我完全同意你的看法。但是,我目前在我的 Appointment 字段中有一个 userId。出于数据规范化的目的,我认为我会使用该 userId 作为外键,并从 Firestore 中的 User 表访问我的用户详细信息。
  • 是的@jdcles12.. 我知道你在说什么.. 但是 Firebase 使用非规范化结构.. 非常不建议使用这种类型的数据组织。如果可以,我建议您查看此链接以了解更多您可以使用的各种技术:angularfirebase.com/lessons/…
猜你喜欢
  • 1970-01-01
  • 2014-12-30
  • 2014-01-03
  • 1970-01-01
  • 2018-03-30
  • 1970-01-01
  • 1970-01-01
  • 2020-10-05
  • 2018-05-07
相关资源
最近更新 更多