Android 在RxJava中创建doIfEmpty操作符

Android 在RxJava中创建doIfEmpty操作符,android,rx-java,Android,Rx Java,我有两个流,第一个流是从数据库获取数据的流,在获取完数据后调用onCompleted()。第二个流是从服务器获取实时数据的流,它从不调用onCompleted()。我想做的是创建一个操作符,如果第一个流(上游)是空流,它可以执行一个操作。以下是示例: getItemFromDatabase() .lift(new DoIfEmptyOperator<Item>(new Action0() { @Override

我有两个流,第一个流是从数据库获取数据的流,在获取完数据后调用
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
                        }
                    }));
getItemFromDatabase()
.lift(新的DoIfEmptyOperator(新的Action0)(){
@凌驾
公开作废通知(){
//数据库是空的
System.out.println(“Yeay成功地执行了一项操作”);
}
}))
.concatWith(getItemFromServer())/--->故意不完成
.subscribe(新订户(){
@凌驾
未完成的公共无效(){
//做某事。。。
}
@凌驾
公共无效申报人(可丢弃的e){
//做某事。。。
}
@凌驾
public void onNext(故事项故事项){
//剂量
}
}));
以下是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;
    }
}
导入接收。可观察;
输入接收用户;
导入rx.functions.Action0;
公共类DoIfEmptyOperator实现了Observable.Operator{
私人行动0行动;
私有布尔值isEmpty=true;
公共DoIfEmptyOperator(操作0操作){
这个动作=动作;
}
@凌驾

公共订阅者您是否考虑过
switchIfEmpty()
?作为使用此运算符的示例-我在GitHub上的以下链接创建了一些代码:

当未发出任何项时,将调用
switchIfEmpty()

但是,如果您希望从api或db获取项目,则可以执行以下操作:

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

只要
getFromDatabase()
getFromApi()
都返回相同的可观察类型。这是Android应用程序中常见的Rx习惯用法。它基本上表示,如果一个项目没有从数据库发出,那么改为从API获取结果。

我建议不要创建操作符。 这可以通过现有运营商轻松实现,如:

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

事实上,如果列表为空,我只想做一个动作,但是switchIfEmpty操作符没有动作作为参数。看起来bellol的解决方案很有效。.提前感谢您回答@blackpather:)@Salaceovanz当然-但是,在函数编程和Rx做事方式方面-使用concat和检索t的解决方案第一项实际上是更干净的选项。当然,您可以测试列表是否为空-但是,这并不是真正的“功能”样式。@blackpanter然而,对于concat,您无法知道获取的第一项是来自api还是来自数据库(因为项类型类似)…如果您知道第一项是从api流获取的(因此假设数据库是空的,并执行一些操作),那么它可能是一个更干净的解决方案:)