RxJava – 获取列表中的每个项目

我有一个返回Observable<ArrayList> ,它是一些Items的id。 我想通过这个列表并使用另一个返回Observable方法下载每个Item。

我如何使用RxJava运算符执行此操作?

这是一个小的自包含示例

 public class Example { public static class Item { int id; } public static void main(String[] args) { getIds() .flatMapIterable(ids -> ids) // Converts your list of ids into an Observable which emits every item in the list .flatMap(Example::getItemObservable) // Calls the method which returns a new Observable .subscribe(item -> System.out.println("item: " + item.id)); } // Simple representation of getting your ids. // Replace the content of this method with yours private static Observable> getIds() { return Observable.just(Arrays.asList(1, 2, 3)); } // Replace the content of this method with yours private static Observable getItemObservable(Integer id) { Item item = new Item(); item.id = id; return Observable.just(item); } } 

请注意, Observable.just(Arrays.asList(1, 2, 3))是您问题中Observable>的简单表示。 您可以在代码中用自己的Observable替换它。

这应该为您提供所需的基础。

p / s:对于这种情况使用flatMapIterable方法,因为它属于Iterable ,如下所示:

 /** * Implementing this interface allows an object to be the target of * the "for-each loop" statement. See *  * For-each Loop *  * * @param  the type of elements returned by the iterator * * @since 1.5 * @jls 14.14.2 The enhanced for statement */ public interface Iterable 

使用Transformer修改源Observable,使用函数调用flatMap 。 您可以将此视为一个两步过程:

  1. 该函数接受每个发出的项( Iterable )并将其作为Observable重新发出
  2. flatMap将每个发出的Observable对象合并为一个Observable

Transformer看起来像这样:

 public class FlattenTransform implements Observable.Transformer, T> { @Override public Observable call(Observable> source) { return source.flatMap(new Func1, Observable>() { @Override public Observable call(Iterable values) { return Observable.from(values); } }); } } 

一旦创建了Transformer,就可以使用compose在源可观察源上应用转换:

 public class Example { private static final ArrayList sourceList = new ArrayList<>(Arrays.asList(new Long[] {1L,2L,3L})); private static final Observable> listObservable = Observable.just(sourceList); private static final FlattenTransform flattenList = new FlattenTransform(); public static void main(String[] args) { listObservable.compose(flattenList).subscribe(printItem); } private static Action1 printItem = new Action1() { @Override public void call(Long item) { System.out.println("item: " + item); } }; } 

使用带有Transformercompose而不是带有Func1flatMap的优点是,如果将来如果你需要再次展平列表,你甚至不必考虑使用哪个运算符(map?flatMap?concatMap ?)。 换句话说,flatmap操作被烘焙到FlattenTransform类中,并且该细节被抽象掉。

变形金刚还有其他好处,例如能够将多个操作链接在一起。

作为flatMapIterable的替代方法,您可以使用flatMap执行此操作:

 Observable.just(Arrays.asList(1, 2, 3)) //we create an Observable that emits a single array .flatMap(numberList -> Observable.fromIterable(numberList)) //map the list to an Observable that emits every item as an observable .flatMap(number -> downloadFoo(number)) //download smth on every number in the array .subscribe(...); private ObservableSource downloadFoo(Integer number) { //TODO } 

我个人认为.flatMap(numberList -> Observable.fromIterable(numberList)).flatMapIterable(numberList -> numberList )更容易阅读和理解。

差异似乎是订单(RxJava2):

  • Observable.fromIterable:将Iterable序列转换为发出序列中项目的ObservableSource。
  • Observable.flatMapIterable:返回一个Observable,它将源ObservableSource发出的每个项目与Iterable中与选择器生成的项目对应的值合并。

使用方法引用,如下所示:

 Observable.just(Arrays.asList(1, 2, 3)) .flatMap(Observable::fromIterable) .flatMap(this::downloadFoo) 

在Kotlin中使用flattenAsFlowable

 repository.getFlowableData(id) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.computation()) .toList() .flattenAsFlowable { it } .map { someMethod(it) } .observeOn(AndroidSchedulers.mainThread()) .subscribe({ }, { onError(it) })