RxJava,平面图的好用例
RxJava, good use case of flatmap
我是 Rx 的新手Java,经常被 flatMap 函数弄糊涂。根据doc,平面图transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable
有人可以给出一个好的用例吗?为什么要将原始 Observable 转换为 Observable(复数),然后将它们转换为单个 Observable。
为什么不直接使用 'map'?
如果您在 Android 中举了一个例子,那就太棒了,否则简单的 Java 就足够了。谢谢
假设你有一个
Observable<Foo> fooObservable;
并且您想调用另一个方法,该方法采用 Foo
并发出 Observable<Bar>
类似于:
public Observable<Bar> getBars(Foo foo);
如果你这样做了:
fooObservable.map(foo -> getBars(foo));
你最终会得到一个 Observable<Observable<Bar>>
因为你已经改变了你的 Foo
-> Observable<Bar>
这可能不是你想要的。
相反,您可以使用 flatMap
其中 "flattens the observable":
Observable<Bar> barObservable = fooObservable.flatMap(foo -> getBars(foo));
我在你的问题上看到了标签 Android
。所以,您可能应该熟悉 Retrofit
.
假设您有两种方法:
public interface FoxreyRestApi {
@POST("/signin")
Observable<SignInResponse> signin(@Body SignInRequest request);
@GET("/user")
Observable<User> getUser(String accessToken);
}
你想获取用户数据,但是你需要accessToken
,其中return是SignInResponse
。
你可以这样做:
1).创建您的 RestAdapter
.
2).一个接一个地查询:
restAdapter.signin(request)
.flatMap(r -> restAdapter.getUser(r.getAccessToken()))
.subscribe(user -> {/*User your user*/});
我经常用它来将一些 UI 事件转换为可观察的后台任务:
ViewObservable.clicks(calculateBtn)
.flatMap(new Func1<OnClickEvent, Observable<Integer>>() {
@Override
public Observable<Integer> call(OnClickEvent onClickEvent) {
return observeBackgroundOperation()
.observeOn(AndroidSchedulers.mainThread())//interaction with UI must be performed on main thread
.doOnError(new Action1<Throwable>() {//handle error before it will be suppressed
@Override
public void call(Throwable throwable) {
progress.setVisibility(View.GONE);
calculateBtn.setEnabled(true);
Toast.makeText(IOCombineSampleActivity.this, R.string.mix_error_message, Toast.LENGTH_SHORT).show();
}
})
.onErrorResumeNext(Observable.<Integer>empty());//prevent observable from breaking
}
})
.subscribe(new Action1<Integer>() {...});
因为使用observable很容易定义后台操作,所以我使用flatMap
将按钮点击事件转换为'something done in background events'(例如通过Retrofit完成的网络请求),然后观察它们。
请注意,flatMap
中的 observable 可以发出单个值,这是在示例中完成的。
这样我就以声明方式定义了 UI 和后台进程之间的交互。
我使用 doOnError
处理错误,然后使用 onErrorResumeNext(Observable.<Integer>empty())
来防止 observable 以 onError
终止。因为我使用 flatMap
,所以我的可观察对象未完成(而内部 flatMap
已完成)并且正在等待下一次点击事件。
您可以在 my article.
中找到完整的代码示例
我是 Rx 的新手Java,经常被 flatMap 函数弄糊涂。根据doc,平面图transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable
有人可以给出一个好的用例吗?为什么要将原始 Observable 转换为 Observable(复数),然后将它们转换为单个 Observable。
为什么不直接使用 'map'?
如果您在 Android 中举了一个例子,那就太棒了,否则简单的 Java 就足够了。谢谢
假设你有一个
Observable<Foo> fooObservable;
并且您想调用另一个方法,该方法采用 Foo
并发出 Observable<Bar>
类似于:
public Observable<Bar> getBars(Foo foo);
如果你这样做了:
fooObservable.map(foo -> getBars(foo));
你最终会得到一个 Observable<Observable<Bar>>
因为你已经改变了你的 Foo
-> Observable<Bar>
这可能不是你想要的。
相反,您可以使用 flatMap
其中 "flattens the observable":
Observable<Bar> barObservable = fooObservable.flatMap(foo -> getBars(foo));
我在你的问题上看到了标签 Android
。所以,您可能应该熟悉 Retrofit
.
假设您有两种方法:
public interface FoxreyRestApi {
@POST("/signin")
Observable<SignInResponse> signin(@Body SignInRequest request);
@GET("/user")
Observable<User> getUser(String accessToken);
}
你想获取用户数据,但是你需要accessToken
,其中return是SignInResponse
。
你可以这样做:
1).创建您的 RestAdapter
.
2).一个接一个地查询:
restAdapter.signin(request)
.flatMap(r -> restAdapter.getUser(r.getAccessToken()))
.subscribe(user -> {/*User your user*/});
我经常用它来将一些 UI 事件转换为可观察的后台任务:
ViewObservable.clicks(calculateBtn)
.flatMap(new Func1<OnClickEvent, Observable<Integer>>() {
@Override
public Observable<Integer> call(OnClickEvent onClickEvent) {
return observeBackgroundOperation()
.observeOn(AndroidSchedulers.mainThread())//interaction with UI must be performed on main thread
.doOnError(new Action1<Throwable>() {//handle error before it will be suppressed
@Override
public void call(Throwable throwable) {
progress.setVisibility(View.GONE);
calculateBtn.setEnabled(true);
Toast.makeText(IOCombineSampleActivity.this, R.string.mix_error_message, Toast.LENGTH_SHORT).show();
}
})
.onErrorResumeNext(Observable.<Integer>empty());//prevent observable from breaking
}
})
.subscribe(new Action1<Integer>() {...});
因为使用observable很容易定义后台操作,所以我使用flatMap
将按钮点击事件转换为'something done in background events'(例如通过Retrofit完成的网络请求),然后观察它们。
请注意,flatMap
中的 observable 可以发出单个值,这是在示例中完成的。
这样我就以声明方式定义了 UI 和后台进程之间的交互。
我使用 doOnError
处理错误,然后使用 onErrorResumeNext(Observable.<Integer>empty())
来防止 observable 以 onError
终止。因为我使用 flatMap
,所以我的可观察对象未完成(而内部 flatMap
已完成)并且正在等待下一次点击事件。
您可以在 my article.
中找到完整的代码示例