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

Android Volley中实现互斥/屏障及RecyclerView批量请求后刷新问题

嘿,这个需求太常见啦!要实现所有Volley请求完成后统一刷新RecyclerView,不用搞复杂的互斥锁,用计数器或者屏障类就能轻松搞定,给你两个实用的方案:

方案一:用原子计数器追踪请求完成状态

这个方案简单直接,核心是用一个线程安全的计数器,每完成一个请求(不管成功还是失败)就累加计数,当计数等于总请求数时,就触发RecyclerView的更新。

// 初始化原子计数器,确保多线程下计数准确
AtomicInteger completedRequests = new AtomicInteger(0);
int totalRequests = vehicleList.size();

for (Vehicle vehicle : vehicleList) {
    String apiUrl = "你的价格API地址?vehicleId=" + vehicle.getId();
    StringRequest priceRequest = new StringRequest(Request.Method.GET, apiUrl,
            response -> {
                // 解析API返回的价格,更新车辆对象
                vehicle.setRealTimePrice(parsePriceFromResponse(response));
                
                // 计数器+1,判断是否所有请求都完成
                if (completedRequests.incrementAndGet() == totalRequests) {
                    // 所有请求完成,在主线程更新RecyclerView
                    adapter.changeDataSetNotify();
                    // 重置计数器,方便下一次20分钟的更新任务使用
                    completedRequests.set(0);
                }
            },
            error -> {
                // 错误场景也要计数,避免卡住更新流程
                if (completedRequests.incrementAndGet() == totalRequests) {
                    adapter.changeDataSetNotify();
                    completedRequests.set(0);
                }
                // 可以给错误的车辆设置默认价格,比如显示"N/A"
                vehicle.setRealTimePrice("N/A");
                Log.e("PriceRequest", "获取车辆" + vehicle.getId() + "价格失败", error);
            });

    // 将请求加入Volley队列执行
    requestQueue.add(priceRequest);
}

方案二:用CountDownLatch实现“屏障”效果

如果你更倾向于“屏障”的思路(所有请求都到达屏障后再继续执行),CountDownLatch是绝佳选择——它就像一个门闩,只有当所有请求都完成(闩锁计数归0),门才会打开,执行后续的UI更新。

int totalRequests = vehicleList.size();
// 初始化闩锁,计数等于请求总数
CountDownLatch priceRequestLatch = new CountDownLatch(totalRequests);

for (Vehicle vehicle : vehicleList) {
    String apiUrl = "你的价格API地址?vehicleId=" + vehicle.getId();
    StringRequest priceRequest = new StringRequest(Request.Method.GET, apiUrl,
            response -> {
                vehicle.setRealTimePrice(parsePriceFromResponse(response));
                // 完成一个请求,闩锁计数-1
                priceRequestLatch.countDown();
            },
            error -> {
                vehicle.setRealTimePrice("N/A");
                // 错误请求也要减少计数,否则闩锁永远不会打开
                priceRequestLatch.countDown();
                Log.e("PriceRequest", "获取车辆" + vehicle.getId() + "价格失败", error);
            });

    requestQueue.add(priceRequest);
}

// 开启一个后台线程等待所有请求完成
new Thread(() -> {
    try {
        // 等待所有请求完成(闩锁计数归0),相当于等待屏障打开
        priceRequestLatch.await();
        // 回到主线程更新RecyclerView(UI操作必须在主线程)
        runOnUiThread(() -> adapter.changeDataSetNotify());
    } catch (InterruptedException e) {
        e.printStackTrace();
        // 被中断时可以做一些容错处理
    }
}).start();

几个关键注意点

  • 错误处理不能忘:不管请求成功还是失败,都必须更新计数器/减少闩锁计数,否则会导致UI永远无法更新。
  • 定时更新的实现:要每20分钟触发一次批量请求,可以用Handler.postDelayed()或者WorkManager(更适合后台定时任务),注意避免内存泄漏。
  • 避免重复请求冲突:如果在当前批量请求还没完成时,又触发了下一次更新,建议先取消队列中未完成的请求,或者重置计数器/闩锁,防止多次调用changeDataSetNotify()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:32:50