Combinazione di completabili RxJava

1. Panoramica

In questo tutorial, giocheremo con il tipo Completabile di RxJava , che rappresenta un risultato di calcolo senza un valore effettivo.

2. Dipendenza RxJava

Includiamo la dipendenza RxJava 2 nel nostro progetto Maven:

 io.reactivex.rxjava2 rxjava 2.2.2 

Di solito possiamo trovare l'ultima versione su Maven Central.

3. Tipo completabile

Completable è simile a Observable con l'unica eccezione che il primo emette segnali di completamento o di errore ma nessun elemento. Laclasse Completable contiene diversi metodi convenienti per crearlo o ottenerlo da diverse sorgenti reattive.

Possiamo generare un'istanza che viene completata immediatamente utilizzando Completable.complete () .

Quindi, possiamo osservare il suo stato utilizzando DisposableCompletableObserver :

Completable .complete() .subscribe(new DisposableCompletableObserver() { @Override public void onComplete() { System.out.println("Completed!"); } @Override public void onError(Throwable e) { e.printStackTrace(); } });

Inoltre, siamo in grado di costruire un completabile esempio dalla Callable, Azione, e Runnable :

Completable.fromRunnable(() -> {});

Inoltre, possiamo ottenere istanze Completable da altri tipi utilizzando Completable.from () o chiamando ignoreElement () sulle sorgenti Forse, Single, Flowable e Observable stesse:

Flowable flowable = Flowable .just("request received", "user logged in"); Completable flowableCompletable = Completable .fromPublisher(flowable); Completable singleCompletable = Single.just(1) .ignoreElement();

4. Concatenamento dei completabili

Possiamo utilizzare il concatenamento di completabili in molti casi d'uso reali quando ci interessa solo il successo dell'operazione:

  • Azioni tutto o niente come eseguire una richiesta PUT per aggiornare un oggetto remoto seguito da un aggiornamento del database locale in caso di successo
  • Registrazione post-factum e journaling
  • Orchestrazione di diverse azioni, ad esempio l'esecuzione di un processo di analisi dopo il completamento di un'azione di importazione

Manterremo esempi semplici e indipendenti dai problemi. Considerare abbiamo diversi completabile casi:

Completable first = Completable .fromSingle(Single.just(1)); Completable second = Completable .fromRunnable(() -> {}); Throwable throwable = new RuntimeException(); Completable error = Single.error(throwable) .ignoreElement();

Per combinare due completabili in uno solo, possiamo usare l' operatore andThen () :

first .andThen(second) .test() .assertComplete();

Possiamo concatenare tutti i completabili necessari. Allo stesso tempo, se almeno una delle sorgenti non riesce a completare, con conseguente completabile non sarà fuoco onComplete () così :

first .andThen(second) .andThen(error) .test() .assertError(throwable);

Inoltre, se uno dei sorgenti è infinito o non raggiunge onComplete per qualche motivo, il Completable risultante non si attiverà mai anche su onComplete ()suError ().

Una buona cosa che possiamo ancora testare questo scenario:

... .andThen(Completable.never()) .test() .assertNotComplete();

5. Composizione di serie di completabili

Immagina di avere un sacco di completabili. Per un caso d'uso pratico, supponiamo di dover registrare un utente all'interno di diversi sottosistemi separati.

Per unire tutti i completabili in uno solo, possiamo usare la famiglia di metodi merge (). L' operatore merge () consente la sottoscrizione a tutte le fonti.

L'istanza risultante viene completata una volta completate tutte le origini . Inoltre, termina con onError quando una qualsiasi delle fonti emette un errore:

Completable.mergeArray(first, second) .test() .assertComplete(); Completable.mergeArray(first, second, error) .test() .assertError(throwable);

Passiamo a un caso d'uso leggermente diverso. Diciamo che dobbiamo eseguire un'azione per ogni elemento ottenuto da un Flowable.

Quindi, vogliamo un singolo completabile sia per il completamento dell'upstream che per tutte le azioni a livello di elemento. L' operatore flatMapCompletable () viene in aiuto in questo caso:

Completable allElementsCompletable = Flowable .just("request received", "user logged in") .flatMapCompletable(message -> Completable .fromRunnable(() -> System.out.println(message)) ); allElementsCompletable .test() .assertComplete();

Allo stesso modo, il metodo sopra è disponibile per il resto delle classi reattive di base come Osservabile , Forse o Singolo.

Come contesto pratico per flatMapCompletable () , potremmo pensare di decorare ogni oggetto con qualche effetto collaterale. Possiamo scrivere una voce di log per ogni elemento completato o creare un'istantanea di archiviazione per ogni azione riuscita.

Infine, potremmo aver bisogno di costruire un completabile da un paio di altre fonti e farlo terminare non appena una di esse viene completata. Ecco dove gli operatori amb possono aiutare.

Il prefisso amb è un'abbreviazione per "ambiguo", che implica l'incertezza su quale Completabile viene completato esattamente. Ad esempio, ambArray ():

Completable.ambArray(first, Completable.never(), second) .test() .assertComplete();

Nota che il Completable sopra può anche terminare con onError () invece di onComplete () a seconda di quale fonte completable termina per primo:

Completable.ambArray(error, first, second) .test() .assertError(throwable);

Inoltre, una volta terminata la prima fonte, è garantito che le fonti rimanenti saranno eliminate.

Che mezzi tutti in esecuzione rimanenti Completables vengono arrestati attraverso Disposable.dispose () e corrispondenti CompletableObservers verranno annullate.

Per quanto riguarda un esempio pratico, possiamo usare amb () quando trasmettiamo un file di backup a più archivi remoti equivalenti. E completiamo il processo una volta terminato il primo backup migliore o ripetiamo il processo in caso di errore.

6. Conclusione

In questo articolo, abbiamo brevemente esaminato il tipo Completabile di RxJava.

Abbiamo iniziato con diverse opzioni per ottenere completabile istanze e poi incatenato e composto Completables utilizzando l'andthen (), merge (), flatMapCompletable (), e amb ... () operatori.

Possiamo trovare la fonte per tutti gli esempi di codice su GitHub.