2017-06-20 77 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(); 
    } 

最後我的看法:

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

問題是,一旦我的frag被創建,.startWith被觸發,而不需要用戶單擊按鈕。然後,如果用戶點擊按鈕,加載狀態永遠不會被調用(.start再次),但只有成功(或錯誤)。 我在這裏錯過了什麼?

再次感謝!

編輯:

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

另一個過程越來越透明位圖,但添加後startWith,我調用不會被調用。如果我把它拿出來,它就像魅力一樣。

回答

1

這只是一個RxJava錯誤,並不真正與Mosby有關。

.startWith(new SignatureViewState.LoadingState())(也許.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發出一些開始的項,在你的情況下永遠不會發生,因此沒有被調用),後面的接收一個具體的對象。使用後者。查找文檔中的差異。 – sockeqwe

+0

哦,我看到了,但我打算在startWith中調用一個方法,以顯示加載微調器 – Leonardo