web-dev-qa-db-fra.com

rxJava2 Combinaison simple, peut-être, exécutable dans des flux complexes

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?

13
Rostyslav Roshak

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

5
Rostyslav Roshak

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.

2
Andri Ihsannudin

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).

0
Fabio