我有2个流,第一个流是从数据库获取数据并在完成数据后调用onCompleted()
的流。第二个流是从服务器获取实时数据的流,从不调用onCompleted()
。我想要做的是创建一个操作符,如果第一个流(上游)是一个空流,它可以执行操作。以下是样本:
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 :(得分:0)
您是否考虑过switchIfEmpty()
?作为使用此运算符的示例 - 我在GitHub上通过以下链接创建了一些代码:
https://github.com/rs146/rxjava-simple/blob/master/src/test/java/SwitchIfEmpty.java
switchIfEmpty()
在没有项目被发出时被调用。
但是,如果您想从api或db获取项目,那么您可以执行以下操作:
Observable.concat(getFromDatabase(), getFromApi()).first();
只要getFromDatabase()
和getFromApi()
都返回相同的Observable Type。这是Android应用中常见的Rx习语。它基本上表明,如果没有从数据库中发出一个项目,那么请从API中获取结果。
答案 1 :(得分:0)
我建议不要创建运营商。 这可以通过这样的现有运营商轻松完成:
getItemFromDatabase()
.toList()
.flatMap(list -> {
if (list.isEmpty()) {
// side effect here
}
return getItemFromServer();
});