Myślę o tym, że używasz, flatMapgdy funkcja, którą chcesz wstawić, map()zwraca Observable. W takim przypadku nadal możesz spróbować użyć, map()ale byłoby to niepraktyczne. Pozwól, że wyjaśnię dlaczego.
Jeśli w takim przypadku zdecydujesz się trzymać map, dostaniesz Observable<Observable<Something>>. Na przykład w twoim przypadku, gdybyśmy użyli wyimaginowanej biblioteki RxGson, która zwróciła metodę Observable<String>z jej toJson()metody (zamiast po prostu Stringzwrócić a ), wyglądałaby następująco:
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
W tym momencie byłoby dość trudne subscribe()do takiego obserwowalnego. Wewnątrz dostaniesz coś, Observable<String>do czego będziesz musiał ponownie subscribe()uzyskać wartość. Które nie jest praktyczne ani przyjemne dla oka.
Aby uczynić to użytecznym, jednym z pomysłów jest „spłaszczenie” tego, co można zaobserwować (można zacząć widzieć, skąd pochodzi nazwa _flat_Map). RxJava oferuje kilka sposobów spłaszczania obserwowalnych i dla uproszczenia załóżmy, że scalenie jest tym, czego chcemy. Scalanie zajmuje zasadniczo kilka obserwowalnych i emituje za każdym razem, gdy emituje którekolwiek z nich. (Wiele osób twierdzi, że zmiana byłaby lepszym rozwiązaniem domyślnym. Ale jeśli emitujesz tylko jedną wartość, to i tak nie ma znaczenia.)
Tak więc zmieniając nasz poprzedni fragment otrzymamy:
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
Jest to o wiele bardziej przydatne, ponieważ subskrybując to (lub mapując, filtrując lub ...) po prostu dostajesz Stringwartość. (Również pamiętać, taki wariant merge()nie istnieje w RxJava, ale jeśli rozumiesz ideę scalenia, to mam nadzieję, że rozumiesz również, jak to by działało).
Zasadniczo dlatego, że takie merge()powinny być prawdopodobnie użyteczne tylko wtedy, gdy uda się zwrócić map()obserwowalny, a więc nie trzeba wpisywać tego w kółko, flatMap()został stworzony jako skrót. Stosuje funkcję mapowania tak jak normalnie map(), ale później zamiast emitować zwracane wartości, „spłaszcza” je (lub scala).
To ogólny przypadek użycia. Jest to najbardziej przydatne w bazie kodu, która używa Rx w całym miejscu i masz wiele metod zwracających obserwowalne, które chcesz połączyć z innymi metodami zwracającymi obserwowalne.
W twoim przypadku jest to również przydatne, ponieważ map()może przekształcić tylko jedną emitowaną wartość w onNext()inną emitowaną wartość onNext(). Ale nie może przekształcić go w wiele wartości, żadnej wartości lub błędu. I jak napisał akarnokd w swojej odpowiedzi (i pamiętaj, że jest znacznie mądrzejszy ode mnie, prawdopodobnie ogólnie, ale przynajmniej jeśli chodzi o RxJava), nie powinieneś rzucać wyjątków od siebie map(). Zamiast tego możesz użyć flatMap()i
return Observable.just(value);
kiedy wszystko idzie dobrze, ale
return Observable.error(exception);
kiedy coś zawiedzie.
Zobacz jego odpowiedź na pełny fragment: https://stackoverflow.com/a/30330772/1402641
subscriber.onError()itd. Wszystkie przykłady, które widziałem, spowodowały błędy w ten sposób. Czy to nie ma znaczenia?