我有代码示例:
private Observable<String> rxFetch() {
return Observable.fromCallable(() -> fetchWebsiteHtml())//fetch source of html
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnError(throwable -> Toast.makeText(this, "Connection problem", Toast.LENGTH_SHORT).show())
.onErrorResumeNext(Observable.empty())
.doOnNext(s ->
rxGetHotMovies(s)//fetch from html some html tags
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnError(throwable -> {
Toast.makeText(this, "Parse list failed somehow", Toast.LENGTH_SHORT).show();
})
.onErrorResumeNext(Observable.empty())
.doOnNext(
hotMovies ->
rxLoastToListView(hotMovies)//fill list with data
.doOnError(throwable -> Toast.makeText(this, "Filling list problem", Toast.LENGTH_SHORT).show())
.onErrorResumeNext(Observable.empty())
.doOnComplete(() -> Log.d(TAG, "rxFetch: xxxxxx"))
.subscribe()
)
.subscribe(hotMovies -> {
for (int i = 0; i < hotMovies.size(); i++) {
Log.d(TAG, "fetch list item: " + hotMovies.get(i).toString());
}
})
);
}
这个可观察的rxFetch
确实:
我的问题是:当我们对其中一个观察者返回另一个必要数据时,是否需要进行嵌套?我想不嵌套observables,但第一个返回数据 - 并且它不允许我使用例如zip,对吧?
答案 0 :(得分:1)
您可能正在寻找flatMap
运算符,它允许您链接反应流。
我会用这种方式重写你的代码:
Observable.fromCallable(() -> fetchWebsiteHtml())
.flatMap(s -> rxGetHotMovies(s))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(hotMovies -> {
// update UI here
}, throwable -> {
// check throwable type and show appropriate error message
});
答案 1 :(得分:1)
习惯的方式是这样的:
private Observable<String> rxFetch() {
return Observable.fromCallable(() -> fetchWebsiteHtml())//fetch source of html
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnError(throwable -> Toast.makeText(this, "Connection problem", Toast.LENGTH_SHORT).show())
.onErrorResumeNext(Observable.empty())
.flatMap(s -> rxGetHotMovies(s)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnError(throwable ->
Toast.makeText(this, "Parse list failed somehow", Toast.LENGTH_SHORT).show())
.onErrorResumeNext(Observable.empty())
.flatMap(hotMovies -> rxLoastToListView(hotMovies)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnError(throwable -> Toast.makeText(this, "Filling list problem", Toast.LENGTH_SHORT).show())
.onErrorResumeNext(Observable.empty())
.doOnComplete(() -> Log.d(TAG, "rxFetch: xxxxxx"))
.subscribe(hotMovies -> {
for (int i = 0; i < hotMovies.size(); i++) {
Log.d(TAG, "fetch list item: " + hotMovies.get(i).toString());
});
}
但是,我建议您抽象出错误处理:
private static <T> Transformer<T, T> whenErrorToast(Function<E extends Throwable, String> messageComposer) {
return source -> source.onErrorResumeNext(e -> Observable
.just(messageComposer.apply(e))
.subscribeOn(AndroidSchedulers.mainThread())
.doOnNext(msg -> Toast.makeText(this, msg Toast.LENGTH_SHORT).show())
.observeOn(Schedulers.io())
.flatMap(msg -> Observable.empty());
}
private Observable<String> rxFetch() {
return Observable.fromCallable(() -> fetchWebsiteHtml())//fetch source of html
.compose(whenErrorToast(e -> "Connection problem"))
.flatMap(s -> rxGetHotMovies(s))
.compose(whenErrorToast(e -> "Parse list failed somehow"))
.flatMap(hotMovies -> rxLoastToListView(hotMovies))
.compose(whenErrorToast(e -> "Filling list problem"))
.doOnComplete(() -> Log.d(TAG, "rxFetch: xxxxxx"))
.subscribe(hotMovies -> {
for (int i = 0; i < hotMovies.size(); i++) {
Log.d(TAG, "fetch list item: " + hotMovies.get(i).toString());
});
}