【问题标题】:RxJava, good use case of flatmapRxJava,flatmap 的好用例
【发布时间】:2015-08-07 06:56:22
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: android rx-java rx-android


    【解决方案1】:

    我在您的问题上看到了标签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*/});
    

    【讨论】:

    • 谢谢,就 Android 和 Retrofit 而言,您的回答是一个非常有用的答案。我在下面标记了@Will 的答案,因为它解释了“平坦”点的概念。希望你不要介意。我已经投票给你了
    • @TungMaiLe,谢谢。我只是想帮助你,让 RxJava 更受欢迎,因为它很棒。威尔的回答更详细,我认为你的决定是绝对正确的
    • 很好的答案。这也是我对 flatmap 的理解:它使得一个接一个地“链接”rxjava 请求成为可能。
    【解决方案2】:

    假设你有一个

    Observable<Foo> fooObservable;
    

    并且您想调用另一个方法,该方法采用 Foo 并发出 Observable&lt;Bar&gt;

    类似:

    public Observable<Bar> getBars(Foo foo);
    

    如果你这样做了:

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

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

    相反,您可以使用 flatMap “扁平化可观察”:

    Observable<Bar> barObservable = fooObservable.flatMap(foo -> getBars(foo));
    

    【讨论】:

      【解决方案3】:

      我经常使用它来将一些 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 完成)然后观察它们。

      注意,flatMap 中的 observable 可以发出单个值,这在 sample 中完成。

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

      您可以在my article 中找到完整的代码示例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-11-22
        • 2018-12-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多