在RxJava中创建doIfEmpty运算符

时间:2017-05-26 09:28:17

标签: android rx-java

我有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()的源代码,但仍然不知道它是如何工作的。

2 个答案:

答案 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();
            });