for循环中进行联网请求数据、for循环中进行异步数据操作,数据排序错乱问题解决;

时间:2020-12-19 14:31:41

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了,这样的数据的顺序还是和原数据的顺序是一致的,并且是并发的异步请求,速度快效率高;