2017-03-07 87 views
8

我遇到的问题是这样的。我需要执行几个请求到服务器。每个下一个请求取决于前一个的结果。 他们看起来像这样(略):RxJava - 链接请求和更新UI

Observable<FileUploadResponse> obsFile = api.uploadFile(); 
Observable<TokenCreateResponse> obsCreateToken = api.createToken(); 
Observable<PaymentResponse> obsPayment = api.submitOrder(); 

我使用flatMap它返回PaymentResponse对象或发出的onError()如果一些不符合要求创建一个可观察的。这工作正常,我可以在一次通话中完成所有请求。

问题是我无法更新这些请求之间的用户界面。使用当前设置,我会在请求启动时显示加载,并在所有请求完成时将其隐藏。有没有办法在这些请求之间更新UI?

我想要的是: 1.文件上传 - 在用户界面上写入消息。 2.创建一个令牌 - 在UI上写一条消息。 3.提交订单 - 在用户界面上撰写消息。 4.一旦完成,隐藏进度对话框。

我的理解是在每个API调用完成时使用onNext()发出一些Observable,然后在全部完成时调用onComplete()。但我该怎么做?

+0

您可以在任何地方使用'doOnNext()'方法在处理管道,看看发生了什么,什么中介结果,当然观察员和SUBCRIBE在各自的线程 – Raghunandan

+0

另一种可能性是包装每个中间类型的常用包装,你可以用它作为你的Subscriber的类型。类似于'api.uploadFile()。flatMap(fileUploadResponse - > Observable.concat(Observable.just(new StatusUpdate(fileUploadResponse)),api.createToken())。flatMap(tokenCreateResponse - > Observable.concat(Observable.just(new StatusUpdate(tokenCreateResponse),api.submitOrder())...' - 一个名为[RxSealedUnions](https://github.com/pakoito/RxSealedUnions)的库对这种方法很有帮助... –

回答

8

你可以通过doOnNextPublishSubject来实现。首先创建一个主题和一些值:

public static final int STATUS_UPLOADING = 0; 
public static final int STATUS_TOKEN = 1; 
public static final int STATUS_SUBMITTING = 2; 
public static final int STATUS_DONE = 3; 

PublishSubject<Integer> status = PublishSubject.create(); 

public Observable<Integer> getStatusStream() { 
    return status; 
} 

然后,当你做你的上传工作,每次的价值只发送到主题:

status.onNext(STATUS_UPLOADING); 

return api.uploadFile() 
    .doOnNext(o -> status.onNext(STATUS_TOKEN)) 
    .flatMap(o -> api.createToken()) 
    .doOnNext(o -> status.onNext(STATUS_SUBMITTING)) 
    .flatMap(o -> api.submitOrder()) 
    .doOnNext(o -> status.onNext(STATUS_DONE)) 

然后你可以订阅Subject和更新你的UI:

model.getStatusStream() 
    .subscribeOn(AndroidSchedulers.mainThread()) 
    .subscribe(
     status -> { 
      view().setMessage(status); 
     }, 
     Throwable.printStackTrace 
    ); 

或者取决于你想如何构建您的应用程序,你可以只调用从每个doOnNext更新视图通话 时间。您可能需要使用observeOn每次在主要的后台线程之间切换。

+0

谢谢,这正是我在找什么。 –