for循环中进行联网请求数据,由于网络请求是异步的,第一个网络请求还没有回调,第二次第三次以及后续的网络请求又已经发出去了,有可能后续的网络请求会先回调;这时我们接收到的数据的排序就会错乱;怎么才能让数据和for循环进行异步操作之前的顺序一样呢;
1、网络请求使用同步请求,串型请求,等第一个网络请求回调后再去请求第二个;
2、递归迭代,异步的网络请求,在当前请求完成后再去递归请求下一个;
但是这两种方式都不是并发的,如果数据特别的多一个一个的去请求就会特别的耗时,我们用for循环异步去请求就会同时相应,速度回很快;
3、重点要说的:for循环中进行联网请求数据,解决数据排序错乱问题。
第一:记录下来这个for循环 原集合的索引位置(集合中的对象添加一个indexes的字段),用来后续的排序;
第二:异步请求后数据会错乱,这时我们根据indexes的大小进行排序;
代码如下:仅留下解决数据排序错乱问题的代码;
private void initNewCars(List<CarInfo> datas) { for (int ii = 0; ii < datas.size(); ii++) { datas.get(ii).indexes = ii; //保存当前车辆的索引位置,等集合遍历完成后进行排序 } AtomicInteger CarSize = new AtomicInteger(); //等所有的集合都联网循环完毕后再去设置数据 List<CarInfo> Cars = new ArrayList<>(); //遍历后对数据进行操作生成新的集合 for (int i = 0; i < datas.size(); i++) { int finalI = i; clwOwnerApi.getAuthVehicleStatus(datas.get(finalI).getVin_code()) //异步网络请求 .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<ResultClw<AuthVehicleStatusBean>>() { @Override public void accept(ResultClw<AuthVehicleStatusBean> result) throws Exception { CarSize.getAndIncrement(); if ("SUCCEED".equals(result.status) && result.data != null) { if (!"0".equals(result.data.getAuditResult()) && result.data.getVehicleStatus()){ }else { CarInfo carInfo = datas.get(finalI); carInfo.isClw = result.data.getVehicleStatus(); Cars.add(carInfo); //数据错乱,需要排序! } } else { UIHelper.showToast(result.errorMessage); } if (CarSize.get() >= datas.size()){ //等所有的集合都循环完成了再去设置数据 L.cc("列表排序前:"+GsonUtils.toJson(Cars)); //根据保存的索引位置进行排序 Collections.sort(Cars, new Comparator<CarInfo>() { @Override public int compare(CarInfo o1, CarInfo o2) { return o1.indexes - o2.indexes; } }); L.cc("列表排序后:"+GsonUtils.toJson(Cars)); } } }, throwable -> { L.e(throwable,throwable.getMessage()); CarSize.getAndIncrement(); UIHelper.showToast("响应服务器失败,请检查网络连接"); }); } }
对集合的排序参考:https://blog.csdn.net/veryisjava/article/details/51675036
CarInfo对象:
public class CarInfo { private String id; private String series; private String owner_name; private String vin_code; private String is_default; private String uuid; private String deliver_date; private String vin_name; private String card_id; private String auth_date; private String mobile; public boolean isClw; public int indexes; //记录当前的位置,用来排序 }
**大致思路:
1、判断集合是否循环完成:异步操作,等所有的异步都完成了再去设置数据;使用AtomicInteger记录数据是否全部遍历完成了;
2、数据错乱问题:先给原数据添加索引位置字段,记录原数据的顺序;异步操作集合后数据错乱,在根据数据的索引字段去排序就OK了,这样的数据的顺序还是和原数据的顺序是一致的,并且是并发的异步请求,速度快效率高;