2017-05-26 31 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

相关问题