java - 结合之前的观测值

标签 java android rx-java2 mosby

我正在尝试使用 RxJava、RxAndroid 和 Mosby3 将两种表单插入结合在一起,但我找不到一种方法来使其工作。

我的结构:

public final class CheckinIntent {

    private final CheckinCommand checkinCommand;
    private final Bitmap signature;

    public CheckinIntent(CheckinCommand checkinCommand, Bitmap signature) {
        this.checkinCommand = checkinCommand;
        this.signature = signature;
    }

    public CheckinCommand getCheckinCommand() {
        return checkinCommand;
    }

    public Bitmap getSignature() {
        return signature;
    }
}

我在哪里激发我的 Intent (MVI 模式):

final Observable<Bitmap> signatureObservable = Observable.just(BitmapFactory.decodeFile(storage.getFile("signs", booking.getBookingId()).getAbsolutePath()));
        final Observable<CheckinCommand> checkinCommandObservable = Observable.just(new CheckinCommand(booking.getBookingId(), booking.getUserId(), booking.getPartnerId(), userDetailsTextView.getText().toString(), "google.com"));

        final Observable<CheckinIntent> intentObservable = Observable.zip(signatureObservable, checkinCommandObservable, (image, command) -> new CheckinIntent(command, image));

        return saveButtonClickObservable
                .flatMap(bla -> intentObservable);

并将它们全部绑定(bind)在一起:

 @Override
    protected void bindIntents() {
        Observable<CheckinViewState> checkinViewStateObservable =
                intent(CheckinView::sendCheckin)
                        .flatMap(checkinIntent -> imageRepository.uploadImage(checkinIntent.getSignature())
                        .flatMap(command ->  bookingRepository.doCheckin(command) <------ PROBLEM HERE, HOW CAN I ACCESS THE COMMAND FROM ABOVE ??
                                .subscribeOn(Schedulers.from(threadExecutor))
                                .map(CheckinViewState.Success::new)
                                .cast(CheckinViewState.class)
                                .startWith(new CheckinViewState.LoadingState())
                                .onErrorReturn(CheckinViewState.ErrorState::new))
                        .observeOn(postExecutionThread.getScheduler());

        subscribeViewState(checkinViewStateObservable, CheckinView::render);
}

Observable<CnhImageResponse> uploadImage(Bitmap bitmap);

我的问题是,我的 uploadImage 返回一个以字符串结尾的内部结构,但是,如何获取返回的字符串,将其添加到我的 command 对象中(在此设置返回的 URL)对象)并继续流程(将我的命令发送到云)?

谢谢!

最佳答案

直接在第一个 flatMap 内的可观察对象上使用 flatMap。在这种情况下,您可以引用 checkinIntent 和命令

 @Override
 protected void bindIntents() {
        Observable<CheckinViewState> checkinViewStateObservable =
                intent(CheckinView::sendCheckin)
                        .flatMap(checkinIntent -> { 
                          return imageRepository.uploadImage(checkinIntent.getSignature()
                                                .flatMap(imageResponse ->  bookingRepository.doCheckin(command) <-- Now you have access to both, command and CnhImageResponse 
                         }) 
                         .subscribeOn(Schedulers.from(threadExecutor))
                         .map(CheckinViewState.Success::new)
                         .cast(CheckinViewState.class)
                         .startWith(new CheckinViewState.LoadingState())
                         .onErrorReturn(CheckinViewState.ErrorState::new))
                         .observeOn(postExecutionThread.getScheduler());

        subscribeViewState(checkinViewStateObservable, CheckinView::render);
}

替代解决方案:传递 Pair<CheckinIntent, Command>bookingRepository.doCheckin(...) 到 Observable像这样:

@Override
protected void bindIntents() {
        Observable<CheckinViewState> checkinViewStateObservable =
                intent(CheckinView::sendCheckin)
                        .flatMap(checkinIntent -> imageRepository.uploadImage(checkinIntent.getSignature()
                                                                 .map(imageResponse -> Pair.create(checkinIntent, imageResponse))) // Returns a Pair<CheckinIntent, CnhImageResponse>
                        .flatMap(pair ->  bookingRepository.doCheckin(pair.first) <-- Now you can access the pair holding both information
                                .subscribeOn(Schedulers.from(threadExecutor))
                                .map(CheckinViewState.Success::new)
                                .cast(CheckinViewState.class)
                                .startWith(new CheckinViewState.LoadingState())
                                .onErrorReturn(CheckinViewState.ErrorState::new))
                        .observeOn(postExecutionThread.getScheduler());

        subscribeViewState(checkinViewStateObservable, CheckinView::render);
}
<小时/>

还有一些其他注意事项:

你几乎想要更喜欢 switchMap()超过flatMap()在 MVI 中。 switchMap 取消之前的订阅,而 flatMap 则不会。这意味着,如果您像在代码中所做的那样进行 flatMap 剪裁,并且无论出于何种原因,在旧的 checkinIntent 尚未完成(即 imageRepository.uploadImage() 仍在进行中)时触发了新的 checkinIntent (即 imageRepository.uploadImage() 仍在进行中),您最终会有两个流这将调用 CheckinView::render因为第一个仍然继续工作并通过您建立的可观察流向下发出结果。 switchMap() 通过在开始“switchMaping”新 Intent 之前取消订阅第一个(未完成的) Intent 来防止这种情况发生,这样您当时只有 1 个流。

构建 CheckinIntent 的方式应移至演示者。对于“转储” View 来说,这有点太多“逻辑”。另外Observable.just(BitmapFactory.decodeFile(...))正在主线程上运行。我建议使用Observable.fromCallable( () -> BitmapFactory.decodeFile(...))因为后者推迟了他的“工作”(位图解码),直到实际订阅了该可观察量,然后您可以应用后台调度程序。 Observable.just() 基本上与:

Bitmap bitmap = BitmapFactory.decodeFile(...); // Here is the "hard work" already done, even if observable below is not subscribed at all.
Observable.just(bitmap);

关于java - 结合之前的观测值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44554608/

相关文章:

java - 具有 2 种不同类型的对象数据

android - 如何在 android 中使用 Dictionary(如 iphone NSDictionary)?

android - 多个模块使用同一个 jar

android - 等到用户停止输入后再在搜索 View 中执行大量搜索

android - Retrofit2 ,Rxjava 中的过滤列表响应

java - RxJava : merge() changes the order of the emitted items?

java - JVM 如何因 OOM 异常而死掉?

java - POST 对象的 facebook 格式(到墙上)

java - 在java中使用用户输入进行反射过程

java - 我的 obj 解析器可能出了什么问题?