2017-05-26 66 views
0

我有2個流,第一個流是從數據庫獲取數據並在完成數據後調用onCompleted()的流。第二個流是從服務器獲取實時數據的流,並且不會調用onCompleted()。我想要做的是創建一個操作符,如果第一個流(上游)是空流,就可以執行操作。下面是示例:在RxJava中創建doIfEmpty運算符

getItemFromDatabase() 
.lift(new DoIfEmptyOperator<Item>(new Action0() { 
         @Override 
         public void call() { 
          //Database is empty 
          System.out.println("Yeay successfully do an action"); 
         } 
        })) 
.concatWith(getItemFromServer()) // -----> intentionally never complete 
.subscribe(new Subscriber<StoryItem>() { 
         @Override 
         public void onCompleted() { 
          //dosomething... 
         } 

         @Override 
         public void onError(Throwable e) { 
          //dosomething... 
         } 

         @Override 
         public void onNext(StoryItem storyItem) { 
          //dosomething 
         } 
        })); 

下面是DoIfEmptyOperator的代碼:

import rx.Observable; 
import rx.Subscriber; 
import rx.functions.Action0; 

public class DoIfEmptyOperator<T> implements Observable.Operator<T,T>{ 
    private Action0 action; 
    private boolean isEmpty = true; 

    public DoIfEmptyOperator(Action0 action) { 
     this.action = action; 
    } 

    @Override 
    public Subscriber<? super T> call(final Subscriber<? super T> childSubscriber) { 

     Subscriber<T> parentSubscriber = new Subscriber<T>() { 
      @Override 
      public void onCompleted() { 
       if(isEmpty) { 
        action.call(); 
       } 

       childSubscriber.onCompleted(); 
      } 

      @Override 
      public void onError(Throwable e) { 
       childSubscriber.onError(e); 
      } 

      @Override 
      public void onNext(T t) { 
       isEmpty = false; 
       childSubscriber.onNext(t); 
      } 
     }; 

     childSubscriber.add(parentSubscriber); 

     return parentSubscriber; 
    } 
} 

但是因爲parentSubscriber onCompleted()在不觸發永遠不會執行的動作,由於下游沒有完成。如果我刪除

.concatWith(getItemFromServer())

,則執行該操作。有關如何解決問題的任何線索?我已經潛入Observable.switchIfEmpty()的源代碼,但仍然不知道它是如何工作的。

回答

0

我會建議不要創建一個操作符。 這可能與現有運營商可以輕鬆完成這樣的:

getItemFromDatabase() 
      .toList() 
      .flatMap(list -> { 
       if (list.isEmpty()) { 
        // side effect here 
       } 
       return getItemFromServer(); 
      }); 
+0

啊從來沒有想過這個,它的工作原理,謝謝:) – SalacceoVanz

0

您是否想過switchIfEmpty()?由於這個操作符的使用的例子 - 我已經創建了GitHub上一些代碼在以下鏈接:

https://github.com/rs146/rxjava-simple/blob/master/src/test/java/SwitchIfEmpty.java

switchIfEmpty()沒有項目被髮射被調用。

但是,如果你想了解從API或數據庫的項目,那麼你可以做類似如下:

Observable.concat(getFromDatabase(), getFromApi()).first(); 

只要兩個getFromDatabase()getFromApi()返回相同的可觀測類型。這是Android應用中常見的Rx習慣用法。它基本上規定,如果一個項目不是從數據庫發出的,那麼就從API獲取結果。

+0

其實我只想做一個動作,如果該列表是空的,但是switchIfEmpty運營商沒有行動參數。看起來像bellol的解決方案作品..預先感謝回答@blackpather :) – SalacceoVanz

+0

@SalacceoVanz肯定 - 然而,在功能編程和Rx方式的做事方面 - 使用concat和檢索第一個項目的解決方案實際上是更清潔的選擇。當然,你可以測試列表是否爲空 - 但是,這不是真正的「功能」風格。 – blackpanther

+0

@blackpanter然而,對於concat,無法知道第一個獲取的項是來自api還是來自數據庫(導致項類型相似)...如果您知道第一個項是從api流獲取的(所以它假設數據庫是空的,並做一些事情),那麼它可能是一個更清潔的解決方案:) – SalacceoVanz

相關問題