RxJava - 链接请求和更新 UI

Posted

技术标签:

【中文标题】RxJava - 链接请求和更新 UI【英文标题】:RxJava - Chaining requests and updating UI 【发布时间】:2017-07-28 00:14:34 【问题描述】:

我遇到的问题是这个。我需要对服务器执行几个请求。每个下一个请求都取决于前一个请求的结果。 它们看起来像这样(缩写):

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

我使用 flatMap 创建了一个单独的 observable,它返回 PaymentResponse 对象或在某些要求未满足时发出 onError()。这工作正常,我可以在一次调用中完成所有请求。

问题是我无法在这些请求之间更新 UI。使用当前设置,我在请求开始时显示加载,并在所有请求完成时隐藏它。有没有办法在这些请求之间更新 UI?

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

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

【问题讨论】:

您可以在处理管道中的任何位置使用doOnNext() 方法来查看正在发生的事情以及中间结果是什么,当然还可以在各个线程上观察和订阅 另一种可能性是将每个中间类型包装在一个公共包装器中,您将使用该包装器作为Subscriber 的类型。 api.uploadFile().flatMap(fileUploadResponse -&gt; Observable.concat(Observable.just(new StatusUpdate(fileUploadResponse)), api.createToken()).flatMap(tokenCreateResponse -&gt; Observable.concat(Observable.just(new StatusUpdate(tokenCreateResponse), api.submitOrder())... 之类的东西 - 一个名为 RxSealedUnions 的库对这种方法很有帮助...... 【参考方案1】:

您可以使用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 并更新您的用户界面:

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

或者,根据您希望如何构建应用程序,您可以每次都从doOnNext 调用更新视图调用。您可能每次都需要使用observeOn 在主线程和后台线程之间切换。

【讨论】:

以上是关于RxJava - 链接请求和更新 UI的主要内容,如果未能解决你的问题,请参考以下文章

链接多个调用 RxJava、Room 和 Retrofit

如何测试 rxjava 链接?

RXJava/Kotlin - 链接单个结果为一个

在页面切换时使用RxJava持续更新UI界面

RxJava:链接可观察对象

使用 RxJava 链接 Retrofit 调用