Android RxJava,flatmap的良好用例

Android RxJava,flatmap的良好用例,android,rx-java,rx-android,Android,Rx Java,Rx Android,我是RxJava新手,经常被flatMap函数弄糊涂。根据flatmap将可观察到的项目转换为可观察到的项目,然后将这些项目的发射平坦化为单个可观察到的项目 有人能给出一个好的用例吗?为什么要将原始的可观察物转换为可观察物(复数),然后将它们转换为单个可观察物 你为什么不用“地图”呢 如果你举一个Android的例子,那就太棒了,否则纯Java就足够了。谢谢假设您有 Observable<Foo> fooObservable; 如果您这样做了: fooObservable.map(

我是RxJava新手,经常被flatMap函数弄糊涂。根据flatmap
将可观察到的项目转换为可观察到的项目,然后将这些项目的发射平坦化为单个可观察到的项目

有人能给出一个好的用例吗?为什么要将原始的可观察物转换为可观察物(复数),然后将它们转换为单个可观察物

你为什么不用“地图”呢

如果你举一个Android的例子,那就太棒了,否则纯Java就足够了。谢谢

假设您有

Observable<Foo> fooObservable;
如果您这样做了:

fooObservable.map(foo -> getBars(foo));
你最终会得到一个
可观察的
,因为你已经改变了你的
Foo
->
可观察的
,这可能不是你想要的

相反,您可以使用“展平可观察对象”的
flatMap

Observable barObservable=foobservable.flatMap(foo->getbar(foo));

我看到了关于你问题的标签
Android
。因此,您可能应该熟悉
改装

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

public interface FoxreyRestApi {

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

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

我经常使用它将一些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>() {...});
ViewObservable.clicks(calculateBtn)
.flatMap(新函数1(){
@凌驾
公共可观察调用(OnClickEvent OnClickEvent){
返回observeBackgroundOperation()
.observeOn(AndroidSchedulers.mainThread())//必须在主线程上执行与UI的交互
.doError(新操作1(){//在将其抑制之前处理错误
@凌驾
公共无效呼叫(可丢弃可丢弃){
progress.setVisibility(View.GONE);
calculateBtn.setEnabled(真);
Toast.makeText(IOCombineSampleActivity.this,R.string.mix_error_message,Toast.LENGTH_SHORT).show();
}
})
.onErrorResumeNext(Observable.empty());//防止Observable中断
}
})
.subscribe(新操作1(){…});
因为使用observable很容易定义后台操作,所以我使用
flatMap
将按钮点击事件转换为“后台事件中完成的事情”(例如网络请求完成了改装),然后观察它们

注意,
flatMap
中的可观察值可以发出单个值,这是在示例中完成的

通过这种方式,我以声明方式定义了UI和后台进程之间的交互。 我使用
doError
处理错误,然后使用
onErrorResumeNext(Observable.empty())
防止Observable以
onError
终止。因为我使用的是
flatMap
,所以我的可观察对象未完成(而内部
flatMap
已完成),正在等待下一次单击事件


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

谢谢,您的答案在Android和改型方面非常有用。我在下面标记了@Will的答案,因为它解释了现场“平坦”的概念。希望你不介意。我投了更高的票yours@TungMaiLe谢谢我只是想帮助你,让RxJava更受欢迎,因为它太棒了。威尔的回答更详细,我认为你的决定绝对正确,这是一个很好的回答。这也是我理解flatmap的方式:它使一个接一个地“链接”rxjava请求成为可能。
public interface FoxreyRestApi {

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

    @GET("/user")
    Observable<User> getUser(String accessToken);
}
restAdapter.signin(request)
    .flatMap(r -> restAdapter.getUser(r.getAccessToken()))
    .subscribe(user -> {/*User your user*/});
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>() {...});