onNext和onComplete的行为

时间:2015-07-23 10:52:14

标签: android reactive-programming rx-java

我有一个Observable,可以在不需要发出值的情况下执行某些操作。我还有一个我希望Observable可以使用的对象列表。因此,对于此列表中的所有元素:doSomething()

Observable.from(uris)
        .flatMap(new Func1<Uri, Observable<Void>>() {
            @Override
            public Observable<Void> call(Uri uri) {
                return createDoSomethingObservable(uri);
            }
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribeOn(Schedulers.io())
        .subscribe(new Observer<Void>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "completed");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Void aVoid) {
                Log.d(TAG, "next");
            }
        });

创建Observable的方法:

Observable<Void> createDoSomethingObservable(final Uri uri) {
    return Observable.create(new Observable.OnSubscribe<Void>() {
        @Override
        public void call(Subscriber<? super Void> subscriber) {
            //doSomething
            subscriber.onNext(null);
            subscriber.onCompleted();
        }
    });
}

现在,当我使用带有3个元素的List运行时,我得到了:

next
next
next
completed

这很好,因为这是我想要的,但我不知道为什么它有效。首先我开始调用onComplete,因为最终observable完成了它的工作并完成了。但当然onNext永远不会在订阅者上调用。反过来也是如此。

所以我的问题是:

  1. 为什么onComplete只调用最后一个列表元素?
  2. 有更好的方法可以解决这个问题吗?

3 个答案:

答案 0 :(得分:7)

为最后一个元素调用

onComplete,因为当链中最早的可观察元素(from(uris))结束时。

预计从flatMap发出的观察结果会调用onComplete。一旦完成(并且call已经返回),则可以处理from的下一次发射。 from完成发出可观察对象后,会调用onComplete并有效地完成链。

答案 1 :(得分:5)

我认为,这些小代码可以帮助您了解onNext( )onComplete()的行为 假设您有一个List<Uri>。我们将其转换为Observable<Uri> 手动

public static Observable<Uri> getUries(List<Uri> uriList){
    return Observable.create(new Observable.OnSubscribe<Uri>() {
        @Override
        public void call(Subscriber<? super Uri> subscriber) {
            for(Uri uri : uriList){
                subscriber.onNext(uri);
            }

            subscriber.onCompleted();
        }
    });
}

或使用Lambda表达式:

public static Observable<Uri> getUries(List<Uri> uriList){
    return Observable.create(subscriber -> {
        for(Uri uri : uriList){
            subscriber.onNext(uri);
        }

        subscriber.onCompleted();
    });
}

如您所见,我们正在迭代输入列表,并为每个元素调用onNext( ),当我们完成将List转换为Observable时,我们调用onComplete()

<强> P.S。 此代码只是演示,从不使用来转换ListObservable。使用运算符Observable.from()

<强>更新

运营商from( )实施:

...
while (true) {
    if (o.isUnsubscribed()) {
        return;
    } else if (it.hasNext()) {
        o.onNext(it.next());
    } else if (!o.isUnsubscribed()) {
        o.onCompleted();
        return;
    } else {
        // is unsubscribed
        return;
    }
}
...

链接:https://github.com/ReactiveX/RxJava/blob/1.x/src/main/java/rx/internal/operators/OnSubscribeFromIterable.java#L75-L87

答案 2 :(得分:1)

onComplete(与onError相同)在可观察链中只被调用一次,这是rxjava的实现方式

我认为你的方法是正确的,所以不需要更好的方法。