Je suis très excité par les nouveaux RxJava Sources
tels que: Single
, Maybe
, Completable
, qui rendent vos classes d'interfaces plus propres et évitent beaucoup d'erreurs lors de la création de votre 'Source' (par exemple en oubliant d'appeler onComplete()
)
Mais il faut beaucoup de passe-partout pour les combiner en un flux complexe.
Par exemple. nous avons une situation commune Android de chargement et de mise en cache des données. Supposons que nous avons 2 sources api
et cache
et nous aimerions les combiner:
public interface Api {
Single<Integer> loadFromNetwork();
}
public interface Cache {
Maybe<Integer> loadFromCache(); //maybe because cache might not have item.
}
essayons de le combiner:
final Single<Integer> result = cache.loadFromCache()
.switchIfEmpty(api.loadFromNetwork());
il ne sera pas compilé, car Maybe
n'a pas de surcharge Maybe.switchIfEmpty(Single):Single
nous devons donc tout convertir:
final Single<Integer> result = cache.loadFromCache()
.switchIfEmpty(api.loadFromNetwork().toMaybe())
.toSingle();
Une autre façon possible de le combiner nécessite également une conversion:
final Single<Integer> result = Observable.concat(
cache.loadFromCache().toObservable(),
api.loadFromNetwork().toObservable()
).firstOrError();
Je ne vois donc aucun moyen d'utiliser les nouvelles sources sans beaucoup de transformations qui ajoutent du bruit de code et créent beaucoup d'objets supplémentaires.
En raison de ces problèmes, je ne peux pas utiliser Single
, Maybe
, Completable
et continuer à utiliser Observable
partout.
Ma question est donc:
Quelles sont les meilleures pratiques pour combiner Single
, Maybe
, Completable
.
Pourquoi ces sources n'ont pas de surcharge pour faciliter le peignage.
Pourquoi ces sources n'ont pas d'ancêtre commun et l'utilisent comme
paramètre de switchIfEmpty
et d'autres méthodes?
P.S. Quelqu'un sait-il pourquoi ces classes n'ont pas de hiérarchie commune?
De mon point de vue, si du code peut fonctionner par exemple avec Completable
, cela fonctionnera également très bien avec Single
et Maybe
?
RxJava 2.1.4 qui a été publié le 22 septembre 2017 ajoute la surcharge nécessaire Maybe.switchIfEmpty(Single):Single
.
Donc, dans le cas où nous aimerions combiner les classes suivantes:
public interface Api {
Single<Integer> loadFromNetwork();
}
public interface Cache {
Maybe<Integer> loadFromCache(); //maybe because cache might not have item.
}
On peut enfin faire:
final Single<Integer> result = cache.loadFromCache()
.switchIfEmpty(api.loadFromNetwork());
L'équipe Rx a fait du bon travail en ajoutant des surcharges supplémentaires à Maybe
, Single
, Observable
, ce qui simplifie leur combinaison.
Quant à la version 2.1.16 nous avons les méthodes suivantes pour combiner Maybe
, Single
et Completable
:
Peut-être : flatMapSingleElement(Single):Maybe
, flatMapSingle(Single):Single
, switchIfEmpty(Single):Maybe
, flatMapCompletable(Completable):Completable
Unique : flatMapMaybe(Maybe):Maybe
, flatMapCompletable(Completable):Completable
Complétable : andThen(Single):Single
, andThen(Maybe):Maybe
Je sais que la question est déjà ancienne, mais il ne semble pas encore avoir de réponse acceptée.
Depuis RxJava 2.1.4, ils ajoutent enfin:
public final Single<T> switchIfEmpty(SingleSource<? extends T> other)
Vous pouvez donc simplifier votre chaîne pour:
cache.switchIfEmpty(api)
Cela devrait être le moyen préféré dans ce cas si vous avez la dernière version de RxJava. Sachez simplement que la méthode est annotée avec @Experimental
afin qu'il puisse être modifié à nouveau à l'avenir.
Je ne suis peut-être pas une réponse complète mais j'essaie de répondre à votre cas d'utilisation spécifique:
je pense que le but de votre tâche de combinaison est de récupérer les données du cache, si le résultat est vide, vous voulez appeler une API distante:
final Single<List<Integer>> single = api.call();
Maybe<List<Integer>> maybe = disk.call();
Single <List<Integer>> composedSingle = maybe.flatMapSingle(new Function<List<Integer>, SingleSource<?>>() {
@Override
public SingleSource<?> apply(List<Integer> integers) throws Exception {
if(integers.isEmpty()) return single;
else return Single.just(integers);
}
});
Je ne l'ai pas testé, mais je pense que cela pourrait être une solution possible (je ne sais pas si c'est le meilleur).