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
相关产品推荐
相关产品推荐

