【问题标题】:Android - Transaction - Task is not yet completeAndroid - 事务 - 任务尚未完成
【发布时间】:2021-09-09 21:00:38
【问题描述】:

我找到了一些“任务尚未完成”的示例,但没有找到任何交易示例。我正在使用事务,因为在我的应用程序中,如果没有互联网连接,我需要操作能够失败。我可以通过交易检测到这一点。

我有一个包含文档的集合。我正在尝试获取文件的名称。有时代码工作正常,但大多数时候我得到“任务尚未完成”错误。令人沮丧的是我有一个“onComplete”的回调,所以当回调被调用时事务没有完成很奇怪。

我在 onCompleteListener() 中得到“任务尚未完成的异常。令人沮丧的是,我什至检查以确保 if (task.isSuccessful() && task.isComplete())。我需要使用延续吗?如果是这样,请提供一个例子 - 我还不太明白。

// Note: states is an ArrayList<String>
//       snapshot is a QuerySnapshot

public void getStatesList(){

    states.clear(); 
    states.add("Select A State");

    db.runTransaction(new Transaction.Function<Void>() {
        @Nullable
        @Override
        public Void apply(@NonNull Transaction transaction) {
            // Collect Snapshot data
            snapshot = db.collection("DATA").get();
            return null;
        }
    }).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {

            if(task.isSuccessful() && task.isComplete()){

                try{
                    for(QueryDocumentSnapshot document : snapshot.getResult()){
                        states.add(document.getId());
                    }
                    sendResponseToActivity("Success", RESULT_OK);
                } catch (Exception e){
                    e.printStackTrace(); // Transaction is not yet complete
                    sendResponseToActivity("Fail", RESULT_OK);
                }
            }
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            if(e.getMessage().contains("UNAVAILABLE"))
                sendResponseToActivity("NoInternet", RESULT_OK);
            else
                sendResponseToActivity("Fail", RESULT_OK);
        }
    });

} // End getStatesList()

【问题讨论】:

  • 我现在尝试将类型 Void 更改为 QuerySnapshot 并将该值返回到 onCompleteListener(而不是使用全局变量:Task 快照),使用延续,使用新线程任务.await() 等等。很可能,我只是不太了解延续性,无法自己解决这个问题。我尝试的一切,我都得到了 task.getResult() 所在的错误。
  • 现在,我已经使用通用(非事务)collection.get() 调用重新编程 - 使用一个处理程序,如果数据为未检索到。这个处理程序是必需的,因为 collection.get() 调用永远不会失败。我相信 get 调用已排队等待连接,直到下一次运行才有用(这是一个设置过程,因此不应再运行)。无论如何,我需要最新的数据,而不是缓存。
  • 我已经开始赏金了。请提供一个编码示例,以便我可以在这里直观地看到我的错误。随意将 Void 更改为 QuerySnapshot,因为这看起来更合适,并且是我最终真正需要的来收集文档 ID。

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


【解决方案1】:

在您的代码中,您调用db.collection("DATA").get(),但这不在事务内部操作(使用transaction.get(docRef)transaction.update(docRef, newData) 等来完成)。仅仅因为“事务”的Task已经完成,并不意味着这个流氓数据库调用已经完成。

如果目的是获取服务器的/DATA 副本并且只获取服务器的副本,请使用Query#get(Source source)Source.SERVER。 (注意:待处理的服务器写入可能会合并到数据中,以反映服务器数据的最新副本)

public void getStatesList(){
    states.clear();
    states.add("Select A State");

    db.collection("DATA").get(Source.SERVER)
        .addOnSuccessListener(querySnapshot -> {
            for(QueryDocumentSnapshot document : querySnapshot){
                states.add(document.getId());
            }
            sendResponseToActivity("Success", RESULT_OK);
        })
        .addOnFailureListener(ex -> {
            if (ex.getMessage().contains("UNAVAILABLE")) {
                sendResponseToActivity("NoInternet", RESULT_OK); // RESULT_OK?
            } else {
                sendResponseToActivity("Fail", RESULT_OK); // RESULT_OK?
            }
        });
}

但是,由于上面的版本使用并修改了全局变量,我会使用:

/** Returns server's list of states */
public Task<ArrayList<String>> getStatesList() {
    return db.collection("DATA").get(Source.SERVER)
        .onSuccessTask(querySnapshot -> {
            ArrayList<String> states = new ArrayList<>();

            // NOTE: states.add("Select A State"); was removed here
            
            for (QueryDocumentSnapshot document : querySnapshot) {
                states.add(document.getId());
            }

            return Tasks.forResult(states);
        });
}

然后像这样使用它:

getStatesList().addOnCompleteListener(task -> {
    if (task.isSuccessful()) {
        ArrayList<String> states = task.getResult();
        // do something with states, like update UI
        // don't forget that "Select A State" isn't in the array
    } else {
        Exception ex = task.getException();
        if (ex.getMessage().contains("UNAVAILABLE")) {
            // offline, do something
        } else {
            // unexpected error, do something
        }
    }
})

【讨论】:

  • 谢谢!这个回复有两点是我真正需要的。首先,我想要来自服务器的实时数据,这适用于我的其他工作领域。其次,我收到异常,当连接不存在时,它会给我一个适当的错误消息。我也不知道您可以向 .get() 添加参数。仅此一项就非常有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多