La forma en que lo pienso es que usas flatMap
cuando la función que querías poner dentro de map()
devuelve un Observable
. En cuyo caso aún podría intentar usarlo, map()
pero no sería práctico. Déjame intentar explicar por qué.
Si en ese caso decidieras seguir map
, obtendrías un Observable<Observable<Something>>
. Por ejemplo, en su caso, si utilizamos una biblioteca RxGson imaginaria, que ha devuelto un Observable<String>
de ella del toJson()
método (en lugar de simplemente devolver una String
) que se vería así:
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
En este punto, sería bastante complicado para subscribe()
un observable. Dentro de él, obtendría un valor Observable<String>
al que volvería a necesitar subscribe()
. Lo cual no es práctico ni agradable de ver.
Entonces, para que sea útil, una idea es "aplanar" este observable de observables (puede comenzar a ver de dónde viene el nombre _flat_Map). RxJava proporciona algunas formas de aplanar los observables y, por simplicidad, supongamos que fusionar es lo que queremos. Merge básicamente toma un montón de observables y emite cada vez que alguno de ellos emite. (Mucha gente argumentaría que cambiar sería un valor predeterminado mejor. Pero si está emitiendo un solo valor, no importa de todos modos).
Entonces, modificando nuestro fragmento anterior obtendríamos:
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
Esto es mucho más útil, porque suscribiéndote a eso (o mapeando, filtrando o ...) solo obtienes el String
valor. (Además, merge()
ten en cuenta que tal variante de no existe en RxJava, pero si entiendes la idea de la fusión, espero que también entiendas cómo funcionaría eso).
Básicamente, porque merge()
probablemente esto solo debería ser útil cuando se logra un map()
retorno de un observable y para que no tenga que escribir esto una y otra vez, flatMap()
se creó como una abreviatura. Aplica la función de mapeo como lo map()
haría normalmente , pero luego, en lugar de emitir los valores devueltos, también los "aplana" (o fusiona).
Ese es el caso de uso general. Es más útil en una base de código que usa Rx en todo el lugar y tiene muchos métodos que devuelven observables, que desea encadenar con otros métodos que devuelven observables.
En su caso de uso, también resulta útil, ya map()
que solo puede transformar un valor emitido en onNext()
otro valor emitido en onNext()
. Pero no puede transformarlo en múltiples valores, ningún valor o un error. Y como akarnokd escribió en su respuesta (y ten en cuenta que es mucho más inteligente que yo, probablemente en general, pero al menos cuando se trata de RxJava) no deberías lanzar excepciones de tu parte map()
. Entonces, en su lugar, puede usar flatMap()
y
return Observable.just(value);
cuando todo va bien, pero
return Observable.error(exception);
cuando algo falla
Consulte su respuesta para obtener un fragmento completo: https://stackoverflow.com/a/30330772/1402641
subscriber.onError()
etc. Todos los ejemplos que he visto tienen errores enrutados de esa manera. ¿Eso no importa?