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.
是您问题中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
。 您可以将此视为一个两步过程:
- 该函数接受每个发出的项(
Iterable
)并将其作为Observable
重新发出 -
flatMap
将每个发出的Observable
对象合并为一个Observable
Transformer看起来像这样:
public class FlattenTransform implements Observable.Transformer, T> { @Override public Observable extends T> call(Observable extends Iterable > 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); } }; }
使用带有Transformer
的compose
而不是带有Func1
的flatMap
的优点是,如果将来如果你需要再次展平列表,你甚至不必考虑使用哪个运算符(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 extends Integer> 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) })