5

我是 RxJava 新手,经常被 flatMap 函数弄糊涂。根据文档,平面图transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable

有人可以为它提供一个好的用例吗?为什么要将原始的 Observable 转换为 Observables(复数)然后将它们转换为单个 Observable。

为什么不直接使用“地图”?

如果您在 Android 中给出一个很棒的示例,否则纯 Java 就足够了。谢谢

4

3 回答 3

28

Android我在你的问题上看到了标签。因此,您可能应该熟悉Retrofit.

让我们想象一下您有两种方法:

public interface FoxreyRestApi {

    @POST("/signin")
    Observable<SignInResponse> signin(@Body SignInRequest request);

    @GET("/user")
    Observable<User> getUser(String accessToken);
}

您想获取用户数据,但您需要accessToken,返回的是SignInResponse.

你可以这样做:

1)。创建您的RestAdapter.

2)。一个接一个地进行查询:

restAdapter.signin(request)
    .flatMap(r -> restAdapter.getUser(r.getAccessToken()))
    .subscribe(user -> {/*User your user*/});
于 2015-08-07T13:06:55.577 回答
13

假设你有一个

Observable<Foo> fooObservable;

你想调用另一个方法,它接受一个Foo并发出一个Observable<Bar>

就像是:

public Observable<Bar> getBars(Foo foo);

如果你这样做了:

fooObservable.map(foo -> getBars(foo));

你最终会得到一个,Observable<Observable<Bar>>因为你已经改变了你的Foo->Observable<Bar>这可能不是你想要的。

相反,您可以使用flatMapwhich “扁平化 observable”:

Observable<Bar> barObservable = fooObservable.flatMap(foo -> getBars(foo));
于 2015-08-07T10:41:20.833 回答
2

我经常使用它将一些 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将按钮点击事件转换为“在后台事件中完成的事情”(例如使用 Retrofit 完成的网络请求),然后观察它们。

请注意,可观察到的 inflatMap可以发出单个值,这是在 sample 中完成的。

通过这种方式,我以声明方式定义了 UI 和后台进程之间的交互。我用 处理错误,doOnError然后用它onErrorResumeNext(Observable.<Integer>empty())来防止 observable 以onError. 因为我使用flatMap,所以我的 observable 没有完成(而 innerflatMap是)并且正在等待下一次点击事件。

您可以在我的文章中找到完整的代码示例。

于 2015-08-07T21:05:22.263 回答