J'ai un observable qui fait quelque chose sans avoir besoin d'émettre une valeur. J'ai aussi une liste d'objets avec lesquels je souhaite que l'Observable fonctionne. Donc, pour tous les éléments de cette liste: doQuelque chose ()
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");
}
});
Et la méthode qui crée l'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();
}
});
}
Maintenant, quand je lance ceci avec une liste avec 3 éléments, je reçois:
next
next
next
completed
ce qui est bien, car c'est ce que je voulais, mais je ne sais pas pourquoi ça marche. J'ai d'abord commencé à appeler onComplete, parce qu'en fin de compte l'observable fait son travail et se termine. Mais bien entendu, onNext n'est jamais appelé sur l'abonné. Il en va de même pour l'inverse.
Donc mes questions sont:
onComplete
est appelé pour le dernier élément parce que c'est à la fin de la première observation observable dans la chaîne (from(uris)
).
Il est prévu que vos variables observables émises par flatMap
appelleront onComplete
. Une fois que cela est fait (et que call
est revenu), la prochaine émission de from
peut alors être traitée. Une fois que from
a fini d'émettre des éléments observables, il appelle onComplete
et la chaîne est terminée, de manière efficace.
Je pense que ce petit code vous aide à comprendre le comportement de onNext( )
et onComplete()
.
Supposons que vous ayez un List<Uri>
. Transformons-le en Observable<Uri>
manuellement.
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();
}
});
}
Ou en utilisant des expressions Lambda:
public static Observable<Uri> getUries(List<Uri> uriList){
return Observable.create(subscriber -> {
for(Uri uri : uriList){
subscriber.onNext(uri);
}
subscriber.onCompleted();
});
}
Comme vous pouvez le constater, nous itérons une liste d’entrées et appelons onNext( )
pour chaque élément. Lorsque nous avons fini de transformer notre List
en Observable
, nous avons appelé onComplete()
.
P.S. Ce code est juste une démonstration, s'il vous plaît, ne l'utilisez jamais pour transformer List
en Observable
. Utilisez l'opérateur Observable.from()
pour cela.
METTRE &AGRAVE; JOUR:
Implémentation de l'opérateur 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;
}
}
...
onComplete
(identique à onError
) n'est appelée qu'une fois pendant la chaîne observable, c'est la manière dont rxjava est implémenté
Je pense que votre approche est correcte, alors un meilleur moyen n'est pas nécessaire.