You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何onComplete方法执行完毕后numPoints变量未更新?

问题分析与解决方案

问题根源

Firebase Firestore的get()方法是异步非阻塞的:调用它后会立刻返回,不会等待网络请求完成就继续执行后续代码。

你的代码里,循环中每个get()的onComplete回调都是在后台线程执行的,而主线程会直接跳过这些异步操作,先执行最后的System.out.println("numPoints is " + numPoints);——这时候所有异步请求还没开始更新numPoints,所以打印的是初始值0。等后续异步请求陆续完成,才会在onComplete里累加并打印中间值,这就导致了输出顺序和预期不符。

解决方案

方案1:用CountDownLatch同步等待(注意:Android主线程慎用,会阻塞UI)

通过CountDownLatch计数,等待所有异步任务完成后再打印最终结果:

private void CalculateBatPoints(ArrayList<String> listBat) {
    numPoints = 0;
    CountDownLatch latch = new CountDownLatch(listBat.size());

    for (int i = 0; i < listBat.size(); i++) {
        db.collection("players").document(listBat.get(i)).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                try {
                    if (task.isSuccessful()) {
                        DocumentSnapshot ds = task.getResult();
                        String pointsStr = ds.getString("gwPoints");
                        if (pointsStr != null) {
                            numPoints += Integer.parseInt(pointsStr);
                            System.out.println(numPoints);
                        }
                    }
                } finally {
                    // 每个任务完成后计数减1
                    latch.countDown();
                }
            }
        });
    }

    try {
        // 阻塞当前线程,直到所有任务完成
        latch.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println("numPoints is " + numPoints);
}

方案2:用FirebaseTasks.whenAll异步等待(推荐Android环境使用)

利用Firebase提供的批量任务工具,异步等待所有请求完成后再处理结果,不会阻塞主线程:

private void CalculateBatPoints(ArrayList<String> listBat) {
    numPoints = 0;
    List<Task<DocumentSnapshot>> taskList = new ArrayList<>();

    // 先收集所有异步查询任务
    for (String playerId : listBat) {
        Task<DocumentSnapshot> queryTask = db.collection("players").document(playerId).get();
        taskList.add(queryTask);
    }

    // 等待所有任务完成后统一处理
    Tasks.whenAll(taskList).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> batchTask) {
            if (batchTask.isSuccessful()) {
                // 遍历所有任务结果累加分数
                for (Task<DocumentSnapshot> singleTask : taskList) {
                    DocumentSnapshot ds = singleTask.getResult();
                    String pointsStr = ds.getString("gwPoints");
                    if (pointsStr != null) {
                        numPoints += Integer.parseInt(pointsStr);
                        System.out.println(numPoints);
                    }
                }
                System.out.println("numPoints is " + numPoints);
            } else {
                // 处理批量请求失败的情况
                System.err.println("批量查询失败:" + batchTask.getException().getMessage());
            }
        }
    });
}

内容的提问来源于stack exchange,提问作者coderMani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 19:06:21