如果我对如何使用 RxJava2 缺乏基本的了解,请提前致歉,因为在我看来这应该是非常基础的东西。我已经为不成功的 Google 搜索绞尽脑汁,所以欢迎任何资源推荐。为了清楚起见,我选择使用我的变通方法代码的“净化”表示。
问题描述
我有一个 RxJava2 函数 asyncCallForList()
返回 Maybe<Arraylist<CustomClass>>
.每个CustomClass
此列表中的对象仅填充了几个基本字段(例如,源数据库仅包含每个项目的唯一标识符和标题字符串)。
每个项目所需的完整数据位于另一个数据库位置,使用另一个函数检索 asyncCallForItem(uid)
,它返回一个 Maybe<CustomClass>
基于唯一标识符,其中封装了CustomClass
具有所有必需的数据。 asyncCallForList()
返回的列表中的每一项都将调用此函数.
所需的功能是在填充列表中的所有对象后更新我的 UI。
解决方法#1
很容易遍历 doOnSuccess()
中的结果数组列表附加到初始 Maybe<Arraylist<CustomClass>>
,然后在 doOnSuccess()
中更新我的 UI在 Maybe<CustomClass>
上由后续异步调用返回。这不是一个可接受的解决方法,因为将进行未知数量的 UI 更新(返回的初始列表可能包含任意数量的项目)并且会影响性能。
解决方法 #2
这得到了预期的结果,但感觉是错误的方法 - 我怀疑有更优雅的 RxJava2 解决方案。基本上,我创建了一个自定义 Observable
其中循环遍历列表中的项目并获取每个项目的完整数据。但是,我每次填充 CustomClass
时都没有更新 UI项目,我增加一个计数器,然后检查计数器是否超过或等于初始列表大小。当满足此条件时,我调用 onComplete()
observable 发射器的方法并在那里更新 UI。
private void fetchRemoteDataAndUpdateUi() {
//Counter reset to zero before any asynchronous calls are made.
int count = 0;
Maybe<ArrayList<CustomClass>> itemList = asyncCallForList();
Consumer<ArrayList<CustomClass>> onListReturnedSuccess;
onListReturnedSuccess = new Consumer<ArrayList<CustomClass >>() {
@Override
public void accept(ArrayList<CustomClass> list) throws Exception {
//Custom observable created here, in which the resulting array list is processed.
listObservable = Observable.create(new ObservableOnSubscribe<CustomClass>() {
@Override
public void subscribe(final ObservableEmitter<CustomClass> e) throws Exception {
for (CustomClass customClass : list) {
final CustomClass thisCustomClass = customClass;
//Call to get full data on list item called here.
asyncCallForItem(customClass.getUid())
.doOnSuccess(new Consumer<CustomClass>() {
@Override
public void accept(CustomClass customClass) throws Exception {
thisCustomClass.update(customClass);
e.onNext(thisCustomClass);
count++;
if (count >= list.size()) {
e.onComplete();
}
}
}).subscribe();
}
}
});
listObservable
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Observer<CustomClass>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(CustomClass customClass) {
//Here I add the populated CustomClass object to an ArrayList field that is utilised by the UI.
listForUi.add(customClass);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
//Here the UI is finally updated once all CustomClass objects have been populated.
updateUi();
}
});
}
};
//Kick everything off.
itemList.doOnSuccess(onListReturnedSuccess).subscribe();
}
最佳答案
flatMap
啦!
asyncCallForList()
.subscribeOn(Schedulers.io())
.flatMapSingle(list ->
Flowable.fromIterable(list)
.flatMapMaybe(item ->
asyncCallForItem(item.id)
.subscribeOn(Schedulers.io())
.doOnSuccess(response -> {
// copy state from the original item
response.text = item.text;
})
, 1) // number of concurrent item calls
.toList()
)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(successList -> { /* update UI */ }, error -> { /* report error */ });
关于android - 如何在 RxJava2 中等待 Maybe 项列表完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49142780/