Il modo in cui ci penso è che usi flatMap
quando la funzione che volevi mettere dentro map()
restituisce un Observable
. Nel qual caso potresti comunque provare a usare map()
ma non sarebbe pratico. Vorrei provare a spiegare il perché.
Se in tal caso decidessi di restare map
, otterrai un Observable<Observable<Something>>
. Ad esempio, nel tuo caso, se usassimo una libreria RxGson immaginaria, che restituiva un metodo Observable<String>
dal suo toJson()
(invece di restituire semplicemente a String
) sarebbe simile a questo:
Observable.from(jsonFile).map(new Func1<File, Observable<String>>() {
@Override public Observable<String>> call(File file) {
return new RxGson().toJson(new FileReader(file), Object.class);
}
}); // you get Observable<Observable<String>> here
A questo punto sarebbe piuttosto complicato osservarlo subscribe()
. Al suo interno si otterrebbe un valore Observable<String>
a cui sarebbe nuovamente necessario subscribe()
ottenere il valore. Che non è pratico o bello da vedere.
Quindi per rendere utile un'idea è "appiattire" questo osservabile di osservabili (potresti iniziare a vedere da dove viene il nome _flat_Map). RxJava offre alcuni modi per appiattire osservabili e per semplicità supponiamo che l' unione sia ciò che vogliamo. L'unione fondamentalmente prende un sacco di osservabili ed emette ogni qualvolta uno di essi emette. (Molte persone sostengono che il cambio sarebbe un valore predefinito migliore. Ma se stai emettendo un solo valore, non importa comunque.)
Quindi modificando il nostro frammento precedente avremmo:
Observable.from(jsonFile).map(new Func1<File, Observable<String>>() {
@Override public Observable<String>> call(File file) {
return new RxGson().toJson(new FileReader(file), Object.class);
}
}).merge(); // you get Observable<String> here
Questo è molto più utile, perché iscrivendoti a questo (o mappando, o filtrando, o ...) ottieni semplicemente il String
valore. ( merge()
Intendiamoci , tale variante di non esiste in RxJava, ma se capisci l'idea di unire, spero che capirai anche come funzionerebbe.)
Quindi, in sostanza, perché merge()
probabilmente dovrebbe essere utile solo quando riesce a map()
restituire un osservabile e quindi non è necessario digitarlo più volte, è flatMap()
stato creato come una scorciatoia. Applica la funzione di mappatura come map()
farebbe normalmente , ma in seguito invece di emettere i valori restituiti li "appiattisce" (o li unisce).
Questo è il caso d'uso generale. È molto utile in una base di codice che utilizza Rx allo stesso posto e hai molti metodi che restituiscono osservabili, che vuoi concatenare con altri metodi che restituiscono osservabili.
Nel tuo caso d'uso sembra essere utile, perché map()
può trasformare solo un valore emesso onNext()
in un altro valore emesso onNext()
. Ma non può trasformarlo in più valori, nessun valore o errore. E come ha scritto akarnokd nella sua risposta (e attenzione che è molto più intelligente di me, probabilmente in generale, ma almeno quando si tratta di RxJava) non dovresti gettare eccezioni dalla tua map()
. Quindi invece puoi usare flatMap()
e
return Observable.just(value);
quando tutto va bene, ma
return Observable.error(exception);
quando qualcosa fallisce.
Guarda la sua risposta per uno snippet completo: https://stackoverflow.com/a/30330772/1402641
subscriber.onError()
ecc. Tutti gli esempi che ho visto hanno instradato errori in questo modo. Non importa?