2017-06-20 5 views
0

フォームを作成しようとしましたが、ユーザーが保存ボタンをクリックして保存インテントが発生し、バックグラウンド処理を行うSignaturePadを持つ送信専用ビューです。送信専用画面でMVIを使用する

私は、次のしている:

プレゼンター:

@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(); 
    } 

最後に私の見解:

問題が発生すると、ユーザーのボタンをクリックせずに.startWithが起動します。 その後、ユーザーがボタンをクリックすると、ロード状態は決して呼び出されません(.startwith again)。成功(またはエラー)のみが呼び出されます。 私はここで何が欠けていますか?

もう一度おねがいします!

編集:

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

別のプロセスが透明なビットマップを取得しているが、startWithを追加した後、私の呼び出し可能に呼ばれることは決してありません。私がそれを取り出すと、それは魅力のように機能します。

答えて

1

これはRxJavaの間違いであり、Mosby関連のものではありません。

.onErrorReturn(SignatureViewState.ErrorState::new)switchMap()から返された観測値に入れてください。

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から返された(意図が発射された後switchMapのみトリガーするため):このように。

startWith()は、「実際に作業する前に、まずこれを放出する」という意味です。 startWith()を元のコードのように適用した場合、オブザーバブルの読み込みが開始されますが、実際には「署名を保存する前に、読み込み状態から開始する」ことが必要です。したがって、startWith()は、 "主な"観測可能なものではなく、 "署名の保存"オブザーバブルの一部でなければなりません。

+0

ありがとうHannes、私はまだRxを学ぶのに苦労しています。私は言及するのを忘れた別の問題がある、私はちょうど私の質問を編集した、大丈夫? – Leonardo

+1

あなたは間違った '.startWith()'メソッドを選んでいます。 '.startWith(bla - > renderLoading());' '.startWith(object)'を使用しないでください。これらは同じ方法ですが、パラメータは完全に異なります。最初のものはObservableのパラメータをとります(そして、これがobservableを渡すことでobservableがいくつかのアイテムを出してから、何も起こらないので何も呼び出されません)、後のものは具体的なオブジェクトをとります。後の方を使用してください。ドキュメントの違いを参照してください。 – sockeqwe

+0

ああ、私はstartWith内のメソッドを呼び出してローディングスピナーを表示することを計画しています – Leonardo

関連する問題