rxjava2 - rxjava tutorial
RxJava: Cómo convertir la Lista de objetos a la Lista de otros objetos (8)
Tengo la Lista de SourceObjects y necesito convertirla a la Lista de ResultObjects.
Puedo buscar un objeto a otro usando el método de ResultObject:
convertFromSource(srcObj);
por supuesto que puedo hacerlo así:
public void onNext(List<SourceObject> srcObjects) {
List<ResultsObject> resObjects = new ArrayList<>();
for (SourceObject srcObj : srcObjects) {
resObjects.add(new ResultsObject().convertFromSource(srcObj));
}
}
pero agradeceré mucho a alguien que pueda mostrar cómo hacer lo mismo usando rxJava .
Como una extensión a Noel gran respuesta. Digamos que la transformación también depende de algunos datos del servidor que pueden cambiar durante la suscripción. En ese caso, use flatMap + scan .
Como resultado, cuando la lista de identificación cambia, las transformaciones se reiniciarán nuevamente. Y cuando los datos del servidor cambien en relación con una identificación específica, también se volverá a transformar un solo elemento.
fun getFarmsWithGroves(): Observable<List<FarmWithGroves>> {
return subscribeForIds() //may change during subscription
.switchMap { idList: Set<String> ->
Observable.fromIterable(idList)
.flatMap { id: String -> transformId(id) } //may change during subscription
.scan(emptyList<FarmWithGroves>()) { collector: List<FarmWithGroves>, candidate: FarmWithGroves ->
updateList(collector, candidate)
}
}
}
Conversión sin bloqueo mediante la función de mapa anidado
val ints: Observable<List<Int>> = Observable.fromArray(listOf(1, 2, 3))
val strings: Observable<List<String>> = ints.map { list -> list.map { it.toString() } }
El método de fábrica Observable.from() permite convertir una colección de objetos en una secuencia Observable. Una vez que tenga una secuencia, puede usar el operador de map para transformar cada elemento emitido. Finalmente, deberá suscribirse al Observable resultante para usar los elementos transformados:
// Assuming List<SourceObject> srcObjects
Observable<ResultsObject> resultsObjectObservable = Observable.from(srcObjects).map(new Func1<SourceObject, ResultsObject>() {
@Override
public ResultsObject call(SourceObject srcObj) {
return new ResultsObject().convertFromSource(srcObj);
}
});
resultsObjectObservable.subscribe(new Action1<ResultsObject>() { // at this point is where the transformation will start
@Override
public void call(ResultsObject resultsObject) { // this method will be called after each item has been transformed
// use each transformed item
}
});
La versión abreviada si usa lambdas se vería así:
Observable.from(srcObjects)
.map(srcObj -> new ResultsObject().convertFromSource(srcObj))
.subscribe(resultsObject -> ...);
No rompas la cadena, así.
Observable.from(Arrays.asList(new String[] {"1", "2", "3", }))
.map(s -> Integer.valueOf(s))
.reduce(new ArrayList<Integer>, (list, s) -> {
list.add(s);
return list;
})
.subscribe(i -> {
// Do some thing with ''i'', it''s a list of Integer.
});
Puedes usar el operador de map . Por ejemplo, si tiene una lista de enteros y desea convertir a una lista de dobles:
List<Integer> li = new ArrayList<>();
Observable.just(li).map( l -> {
List<Double> lr = new ArrayList<Double>();
for(Integer e:l) {
lr.add(e.doubleValue());
}
return lr;
});
Pero todo es mucho más natural si puede controlar lo observable y cambiarlo para observar elementos individuales en lugar de colecciones. El mismo código que convierte elementos enteros simples en elementos dobles:
Observable.just(1,2,3).map( elem -> elem.doubleValue())
Si desea mantener las
Lists
emitidas por la fuente
Observable
pero convertir los contenidos, es decir,
Observable<List<SourceObject>>
a
Observable<List<ResultsObject>>
, puede hacer algo como esto:
Observable<List<SourceObject>> source = ...
source.flatMap(list ->
Observable.fromIterable(list)
.map(item -> new ResultsObject().convertFromSource(item))
.toList()
.toObservable() // Required for RxJava 2.x
)
.subscribe(resultsList -> ...);
Esto asegura un par de cosas:
-
Se mantiene el número de
Lists
emitidas por elObservable
. es decir, si la fuente emite 3 listas, habrá 3 listas transformadas en el otro extremo -
El uso de
Observable.fromIterable()
garantizará que elObservable
interno termine de modo que se pueda usartoList()
Si lo que necesita es simplemente
List<A>
a
List<B>
sin manipular el resultado de
List<B>
.
La versión más limpia es:
List<A> a = ... // ["1", "2", ..]
List<B> b = Observable.from(a)
.map(a -> new B(a))
.toList()
.toBlocking()
.single();
Si su
Observable
emite una
List
, puede usar estos operadores:
-
flatMapIterable
(transforma tu lista en un observable de elementos) -
map
(transforma tu artículo en otro artículo) -
Operadores
toList
(transforman un Observable completado en un Observable que emite una lista de elementos del Observable completado)Observable<SourceObjet> source = ... source.flatMapIterable(list -> list) .map(item -> new ResultsObject().convertFromSource(item)) .toList() .subscribe(transformedList -> ...);