Rxjava zip 运算符通过检查第一个 Observable android 的数据来过滤第二个 Observable
Rxjava zip operator filter second Observable by checking data with first Observable android
我正在使用 .zip
运算符组合 2 API calls
我想要的
我想根据 1st Observable
中的某些 ids
从 2nd Observable
中获取筛选值
例
1st Observable
returns 数据喜欢(示例数据)
"categories": [
{
"category": "1",
"category_name": "Wedding Venues",
"category_photo_url": "http://www.marriager.com/uploads/album/0463373001465466151-0463467001465466151.jpeg",
"category_type_id": "1",
2nd Observable
returns 数据如:
"data": [
{
"cat_id": "1",
"category_name": "Wedding Venues",
"status": "1",
"order_id": "1",
"category_type_id": "1"
},
我想将我的第二个 Observable 数据过滤为仅 return 值匹配来自第一个 Observable
的 category_type_id
我的代码
Observable obsService = retrofitService.loadService(getSharedPref().getVendorId());
Observable obsCategory = retrofitService.loadCategory();
Observable<ServiceAndCategory> obsCombined = Observable.zip(obsService.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()), obsCategory.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()), new Func2<ServiceModel, CategoryModel, ServiceAndCategory>() {
@Override
public ServiceAndCategory call(ServiceModel serviceModel, CategoryModel categoryModel) {
return new ServiceAndCategory(serviceModel, categoryModel);
}
});
obsCombined.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io());
obsCombined.subscribe(new Subscriber<ServiceAndCategory>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
if (e instanceof UnknownHostException || e instanceof ConnectException) {
mPresenter.onNetworkError();
} else if (e instanceof SocketTimeoutException) {
mPresenter.onTimeOutError();
} else {
mPresenter.onServerError();
}
}
@Override
public void onNext(ServiceAndCategory model) {
mPresenter.onSuccess(model);
}
});
编辑
基本上我想应用以下逻辑
this.categoryList = combinedModel.categoryModel.getData();
serviceList = combinedModel.serviceModel.getData().getCategories();
for (int i = 0; i < serviceList.size(); i++) {
for (int j = 0; j < categoryList.size(); j++) {
if (!serviceList.get(i).getCategoryTypeId().equals(categoryList.get(j).getCategoryTypeId())) {
categoryList.remove(j);
}
}
}
您可以使用地图和列表以反应式方法应用此过滤,首先将所有类别收集到地图,将所有服务收集到列表,将它们压缩在一起,然后根据类别地图过滤服务列表:
Observable<HashMap<Integer, CategoryData>> categoriesMapObservable =
obsCategory
.flatMapIterable(CategoryModel::getData)
.reduce(new HashMap<>(),
(map, categoryData) -> {
map.put(categoryData.getCategoryTypeId(), categoryData);
return map;
}
);
Observable<List<ServiceData>> serviceListObservable = obsService
.map(ServiceModel::getData);
Observable obsCombined =
Observable.zip(
categoriesMapObservable
.subscribeOn(Schedulers.io()),
serviceListObservable
.subscribeOn(Schedulers.io()),
Pair::new
)
.flatMap(hashMapListPair -> {
HashMap<Integer, CategoryData> categoriesMap = hashMapListPair.first;
return Observable.from(hashMapListPair.second)
.filter(serviceData -> categoriesMap.containsKey(serviceData.getCategoryTypeId()))
.toList();
}, (hashMapListPair, serviceDataList) -> new Pair<>(hashMapListPair.first.values(), serviceDataList));
输出结果取决于你,这里我在最后应用了一个 flatMap()
的选择器,它将创建一对 CategoryData
的集合和一个 ServiceData
的过滤列表,您当然可以为此创建所需的任何自定义对象。
我不确定你是否从中获得了很多,从复杂性的角度来看它似乎更有效,假设 HashMap 是 O(1),其中类别是 N,服务是 M,你在这里有 N + M (N 构建地图,M 迭代列表并查询地图),而您的天真实现将是 N x M.
至于代码的复杂性,我不确定是否值得,您可以在 zip 的末尾应用您的逻辑进行过滤,或者使用一些可能更有效地进行过滤的库。
P.S observerOn(AndroidSchedulers.mainThread(
) 是不必要的,所以我删除了它。
我正在使用 .zip
运算符组合 2 API calls
我想要的
我想根据 1st Observable
ids
从 2nd Observable
中获取筛选值
例
1st Observable
returns 数据喜欢(示例数据)
"categories": [
{
"category": "1",
"category_name": "Wedding Venues",
"category_photo_url": "http://www.marriager.com/uploads/album/0463373001465466151-0463467001465466151.jpeg",
"category_type_id": "1",
2nd Observable
returns 数据如:
"data": [
{
"cat_id": "1",
"category_name": "Wedding Venues",
"status": "1",
"order_id": "1",
"category_type_id": "1"
},
我想将我的第二个 Observable 数据过滤为仅 return 值匹配来自第一个 Observable
的 category_type_id我的代码
Observable obsService = retrofitService.loadService(getSharedPref().getVendorId());
Observable obsCategory = retrofitService.loadCategory();
Observable<ServiceAndCategory> obsCombined = Observable.zip(obsService.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()), obsCategory.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()), new Func2<ServiceModel, CategoryModel, ServiceAndCategory>() {
@Override
public ServiceAndCategory call(ServiceModel serviceModel, CategoryModel categoryModel) {
return new ServiceAndCategory(serviceModel, categoryModel);
}
});
obsCombined.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io());
obsCombined.subscribe(new Subscriber<ServiceAndCategory>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
if (e instanceof UnknownHostException || e instanceof ConnectException) {
mPresenter.onNetworkError();
} else if (e instanceof SocketTimeoutException) {
mPresenter.onTimeOutError();
} else {
mPresenter.onServerError();
}
}
@Override
public void onNext(ServiceAndCategory model) {
mPresenter.onSuccess(model);
}
});
编辑
基本上我想应用以下逻辑
this.categoryList = combinedModel.categoryModel.getData();
serviceList = combinedModel.serviceModel.getData().getCategories();
for (int i = 0; i < serviceList.size(); i++) {
for (int j = 0; j < categoryList.size(); j++) {
if (!serviceList.get(i).getCategoryTypeId().equals(categoryList.get(j).getCategoryTypeId())) {
categoryList.remove(j);
}
}
}
您可以使用地图和列表以反应式方法应用此过滤,首先将所有类别收集到地图,将所有服务收集到列表,将它们压缩在一起,然后根据类别地图过滤服务列表:
Observable<HashMap<Integer, CategoryData>> categoriesMapObservable =
obsCategory
.flatMapIterable(CategoryModel::getData)
.reduce(new HashMap<>(),
(map, categoryData) -> {
map.put(categoryData.getCategoryTypeId(), categoryData);
return map;
}
);
Observable<List<ServiceData>> serviceListObservable = obsService
.map(ServiceModel::getData);
Observable obsCombined =
Observable.zip(
categoriesMapObservable
.subscribeOn(Schedulers.io()),
serviceListObservable
.subscribeOn(Schedulers.io()),
Pair::new
)
.flatMap(hashMapListPair -> {
HashMap<Integer, CategoryData> categoriesMap = hashMapListPair.first;
return Observable.from(hashMapListPair.second)
.filter(serviceData -> categoriesMap.containsKey(serviceData.getCategoryTypeId()))
.toList();
}, (hashMapListPair, serviceDataList) -> new Pair<>(hashMapListPair.first.values(), serviceDataList));
输出结果取决于你,这里我在最后应用了一个 flatMap()
的选择器,它将创建一对 CategoryData
的集合和一个 ServiceData
的过滤列表,您当然可以为此创建所需的任何自定义对象。
我不确定你是否从中获得了很多,从复杂性的角度来看它似乎更有效,假设 HashMap 是 O(1),其中类别是 N,服务是 M,你在这里有 N + M (N 构建地图,M 迭代列表并查询地图),而您的天真实现将是 N x M.
至于代码的复杂性,我不确定是否值得,您可以在 zip 的末尾应用您的逻辑进行过滤,或者使用一些可能更有效地进行过滤的库。
P.S observerOn(AndroidSchedulers.mainThread(
) 是不必要的,所以我删除了它。