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.

中找到完整的代码示例