【问题标题】:Synchronized Java OnComplete Method同步 Java OnComplete 方法
【发布时间】:2019-03-23 23:57:42
【问题描述】:

我正在尝试访问 Firestore 集合中的一些数据。然后我试图返回该交易数组。但是由于 OnComplete 方法,我无法执行此操作。

public ArrayList<Transaction> getTransactions(){

    //initializing firebase auth object
    firebaseAuth = FirebaseAuth.getInstance();
    FirebaseUser currentUser = firebaseAuth.getCurrentUser();
    //Establishing database connection
    db = FirebaseFirestore.getInstance();

    DocumentReference docRef = db.collection("users").document(currentUser.getEmail());

    //this is the array I am trying to return.
    ArrayList<Transaction> trans = new ArrayList<>();

    docRef.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(TAG, "DocumentSnapshot data: " + document.getData());

                    //update the array with the data received.
                    trans = (ArrayList<Transaction>) document.getData().get("transactions");


                } else {
                    Log.d(TAG, "No such document");
                }
            } else {
                Log.d(TAG, "get failed with ", task.getException());
            }
        }
    });

    return trans;
}

返回的输出是一个空列表,因为在 getTransactions() 返回后触发了 onComplete 方法。

【问题讨论】:

  • 您无法返回尚未加载的数据。并且没有办法让 Android 在执行return trans 语句之前等待数据加载,因为这会阻止用户与您的应用程序交互。任何需要数据的代码都需要在onComplete 内或从那里调用。参见例如stackoverflow.com/a/50277198stackoverflow.com/a/50435519
  • @FrankvanPuffelen 嘿,谢谢您的回复。我查看了您发送的第二个链接。我不确定如何使用我的代码实现您的解决方案。如果您能帮助我,我将不胜感激。
  • 两个答案都显示了如何为您的回调实现自定义接口。 Fred 的回答还显示了针对您的案例量身定制的实现。如果您通过链接的答案使其工作,您还可以将需要数据的代码嵌入到 onComplete 方法中。

标签: java android firebase google-cloud-firestore


【解决方案1】:

如 cmets 中所述,无法返回尚未加载的数据,因此您可以通过传播回调来实现此目的的一种方法。这是一个简单的例子:

interface OnTransactionListReceivedListener {
     void onTransactionListReceived(List<Transaction> result);
}

public void getTransactions(OnTransactionListReceivedListener listener){

  //initializing firebase auth object
  firebaseAuth = FirebaseAuth.getInstance();
  FirebaseUser currentUser = firebaseAuth.getCurrentUser();
  //Establishing database connection
  db = FirebaseFirestore.getInstance();

  DocumentReference docRef = db.collection("users").document(currentUser.getEmail());

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

          if (task.isSuccessful()) {
              DocumentSnapshot document = task.getResult();
              if (document.exists()) {
                listener.onTransactionListReceived((ArrayList<Transaction>) document.getData().get("transactions"));
              } else {
                  Log.d(TAG, "No such document");
              }
          } else {
              Log.d(TAG, "get failed with ", task.getException());
          }
      }
  });;
}

我们定义了一个接口,它有一个方法,一旦接收到列表就会被调用。这是我们的回调。一旦 firebase 返回列表,调用者将收到此列表。您可以调用该方法,例如:

getTransactions(new OnTransactionListReceivedListener() {
  public void onTransactionListReceived(List<Transaction> result) {
      // Use the list here
  }
});

当然,您可能需要进一步传播回调,这很容易退化为所谓的回调地狱。这就是为什么有些人更喜欢一种看似同步的方法,但实际上它是异步的,即reactive streamsfutures

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-11
    • 1970-01-01
    • 1970-01-01
    • 2022-12-10
    • 2011-09-21
    • 2011-11-08
    相关资源
    最近更新 更多