First of all, let me show the UI
First, query list of Head from remote server API1 by parameter tab1 and return list. Second, traverse list and query the body list for every Head through API2 and combine the head and corresponding list. Finally, after finish traversal, return List<Wrapper<Head, List>> data to show the UI.
It's better to use one RxJava block combine with Retrofit. My solution is as below, but it's not elegant enough. This should be a very common requirement so that it is better have a better solution for anyone to reference.
Thanks for all in advance. Hope I have described the requirement clearly.
First. query list of Header.
public void queryListData(LifecycleOwner lifecycleOwner, MaterialZone mz, int pageNum) {
VersaApiService.INSTANCE.getService(MaterialService.class)
.queryMaterialCategory(/*mz.getZoneId()*/"9223372036854775807", mVerticalPageNum, VERTICAL_PAGE_SIZE)
.compose(RxUtil.applyScheduler(lifecycleOwner))
.map(new Function<PageModel<Header>, List<Header>>() {
@Override
public List<Header> apply(@NonNull PageModel<Header> pageResult) throws Exception {
return pageResult.getResult().getRecords();
}
})
.subscribe(new Consumer<List<Header>>() {
@Override
public void accept(List<Header> headers) throws Exception {
mHeader.setValue(headers);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
VLog.d(HORIZONTAL_PAGE_SIZE + ", " + VERTICAL_PAGE_SIZE);
VLog.d("onError");
}
}, new Action() {
@Override
public void run() throws Exception {
// Complete
VLog.d("onComplete");
}
});
}
Second. Query list of Body for every Header in traversal.
private MediatorLiveData<List<HeaderBodyWrapper>> mGroups = new MediatorLiveData<>();
private MutableLiveData<List<Header>> mHeader = new MutableLiveData<>();
public void init(LifecycleOwner lifecycleOwner) {
mGroups.addSource(mHeader, value -> {
queryBodyList(lifecycleOwner, value);
});
}
public void queryBodyList(LifecycleOwner lifecycleOwner, List<Header> headers) {
List<HeaderBodyWrapper> result = new ArrayList<>();
for (Header header : headers) {
VersaApiService.INSTANCE.getService(MaterialService.class)
.queryMaterial(header.getCategoryId(), mVerticalPageNum, VERTICAL_PAGE_SIZE)
.compose(RxUtil.applyScheduler(lifecycleOwner))
.map(new Function<PageModel<Body>, List<Body>>() {
@Override
public List<Body> apply(@NonNull PageModel<Body> materialGroupPageModel) throws Exception {
return materialGroupPageModel.getResult().getRecords();
}
})
.subscribe(new Consumer<List<Body>>() {
@Override
public void accept(List<Body> bodies) throws Exception {
// Combine header and body list.
HeaderBodyWrapper wrapper = new HeaderBodyWrapper();
wrapper.setMaterialGroup(header);
wrapper.setMaterials(bodies);
result.add(wrapper);
VLog.d("onNext");
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
VLog.d(HORIZONTAL_PAGE_SIZE + ", " + VERTICAL_PAGE_SIZE);
VLog.d("onError");
}
}, new Action() {
@Override
public void run() throws Exception {
// Complete
VLog.d("onComplete");
// TODO: Set value when all query.
if (result.size() == headers.size()) {
mGroups.setValue(result);
}
}
});
}
}