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

时间:2015-01-19 23:08:03

标签: java monads reactive-programming rx-java

我有一个返回Observable<ArrayList<Long>>的方法,它是某些项目的ID。我想浏览此列表并使用另一种返回Observable<Item>的方法下载每个项目。

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

5 个答案:

答案 0 :(得分:51)

这是一个小的自包含示例

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<Item>
                .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<List<Integer>> getIds() {
        return Observable.just(Arrays.<Integer>asList(1, 2, 3));
    }

    // Replace the content of this method with yours
    private static Observable<Item> getItemObservable(Integer id) {
        Item item = new Item();
        item.id = id;
        return Observable.just(item);
    }
}

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

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

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

/**
 * Implementing this interface allows an object to be the target of
 * the "for-each loop" statement. See
 * <strong>
 * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides /language/foreach.html">For-each Loop</a>
 * </strong>
 *
 * @param <T> the type of elements returned by the iterator
 *
 * @since 1.5
 * @jls 14.14.2 The enhanced for statement
  */
 public interface Iterable<T>

答案 1 :(得分:5)

作为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)

答案 2 :(得分:4)

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

  1. 该函数接受每个发出的项目(Iterable<T>)并将其重新发布为Observable<T>
  2. flatMap将每个发出的Observable<T>个对象合并为一个Observable<T>
  3. Transformer看起来像这样:

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

    创建Transformer后,您可以使用compose在源可观察源上应用转换:

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

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

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

答案 3 :(得分:1)

在Kotlin中使用flattenAsFlowable

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

答案 4 :(得分:0)

对于Kotlin

 Observable
        .fromIterable(listOfChallenges) // list of challenges which contain challenge ID
        .flatMap { eachChallenge ->
            getChallengeDetail(eachChallenge.challengeUid!!) // fetch details of each challenge
        }
        .toList() // map to list
        .subscribe({ listOfEachChallengesDetail ->

        }, {
            // error
        })