在仅发送屏幕上使用MVI

时间:2017-06-20 18:43:06

标签: android rx-java2 mosby

我正在尝试创建一个包含SignaturePad的表单,仅发送视图,一旦用户点击保存按钮,就会触发保存意图并进行后台处理。

我有以下内容:

主讲人:

@Override
    protected void bindIntents() {
        Observable<SignatureViewState> observable =
                intent(SignatureView::saveSignature)
                        .switchMap(intent -> Observable.fromCallable(() ->
                                storage.createFile(intent.getFullPath(), intent.getName(), intent.getImage()))
                                .subscribeOn(Schedulers.from(threadExecutor)))
                        .map(SignatureViewState.SuccessState::new)
                        .cast(SignatureViewState.class)
                        .startWith(new SignatureViewState.LoadingState())
                        .onErrorReturn(SignatureViewState.ErrorState::new)
                        .observeOn(postExecutionThread.getScheduler());

        subscribeViewState(observable, SignatureView::render);
    }

SignatureFragment:

@Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        saveButtonClickObservable = RxView.clicks(saveBtn)
                .share()
                .map(bla -> true);

compositeDisposable.add(saveButtonClickObservable.subscribe());

...

@Override
    public Observable<SaveSignatureIntent> saveSignature() {
        Observable<SaveSignatureIntent> saveSignatureIntentObservable =
                Observable.just(new SaveSignatureIntent(savePath, bookingId + ".png", null));

        Observable<SaveSignatureIntent> saveSignatureIntent =
                Observable.zip(signatureBitmapObservable, saveSignatureIntentObservable,
                (signature, intent) -> new SaveSignatureIntent(intent.fullPath, intent.name, signature));

        return saveButtonClickObservable
                .flatMap(bla -> saveSignatureIntent);
    }

    @Override
    public void render(SignatureViewState state) {
        if(state instanceof SignatureViewState.LoadingState)
            renderLoading();
        else if (state instanceof SignatureViewState.SuccessState)
            renderSuccess();

        if(state instanceof SignatureViewState.ErrorState)
            renderError();
    }

最后我的观点:

public interface SignatureView extends MvpView {
    Observable<SignatureFragment.SaveSignatureIntent> saveSignature();
    void render(SignatureViewState state);
}

问题是,一旦我的frag被创建,.startWith就会被触发,而无需用户点击按钮。 之后,如果用户单击该按钮,则永远不会调用加载状态(.startwith再次),而只调用成功(或错误)。 我在这里缺少什么?

再次感谢!

编辑:

signatureBitmapObservable = Observable.fromCallable(() -> signaturePad.getTransparentSignatureBitmap(true))
                .subscribeOn(Schedulers.io())
                .startWith(bla -> renderLoading());

另一个过程是获得透明的Bitmap,但在添加startWith后,我的callable永远不会被调用。如果我把它拿出来,它就像一个魅力。

1 个答案:

答案 0 :(得分:1)

这只是一个RxJava错误,而不是真正与Mosby有关。

.startWith(new SignatureViewState.LoadingState())(可能.onErrorReturn(SignatureViewState.ErrorState::new))放入switchMap()返回的observable中。像这样:

 intent(SignatureView::saveSignature)
       .switchMap(intent -> Observable.fromCallable(() ->
                               storage.createFile(intent.getFullPath(), intent.getName(), intent.getImage()))
                                .subscribeOn(Schedulers.from(threadExecutor))
                            .map(SignatureViewState.SuccessState::new)
                            .cast(SignatureViewState.class)
                            .startWith(new SignatureViewState.LoadingState())
                            .onErrorReturn(SignatureViewState.ErrorState::new)
       ) // end of switchMap
       .observeOn(postExecutionThread.getScheduler());

从switchMap返回的observable只在用户点击你的按钮时启动(因为switchMap只在触发意图后触发)。

startWith()表示“在你做真正的工作之前,首先发出这个”。如果你原始代码剪切时应用startWith(),显然它是可观察的开始加载,但你真正想要的是“在保存签名之前,从加载状态开始”。因此startWith()必须是“保存签名”可观察的一部分,而不是“主要”可观察本身的一部分。