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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28035090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 05:29:44  来源:igfitidea点击:

RxJava - fetch every item on the list

javamonadsreactive-programmingrx-java

提问by k_wisniewski

I have a method that returns an Observable<ArrayList<Long>>, which are ids of some Items. I'd like to go through this list and download every Item using another method that returns Observable<Item>.

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

How would I do this using RxJava operators?

我将如何使用 RxJava 运算符做到这一点?

采纳答案by Miguel Lavigne

Here's a small self contained example

这是一个小的自包含示例

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);
    }
}

Please note that Observable.just(Arrays.<Integer>asList(1, 2, 3))is a simple representation of Observable<ArrayList<Long>>from your question. You can replace it with your own Observable in your code.

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

This should give you the basis of what you need.

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

p/s : Use flatMapIterablemethod for this case since it belongs to Iterableas below explaining:

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>

回答by weefbellington

Use a Transformerthat modifies the source Observable, calling a flatMapon it with a function. You can think of this as a 2-step process:

使用一个修改源 Observable的TransformerflatMap用一个函数调用它。您可以将其视为一个 2 步过程:

  1. The function takes each emitted item (an Iterable<T>) and re-emits it as an Observable<T>
  2. flatMaptakes each of these emitted Observable<T>objects an merges them into a single Observable<T>
  1. 该函数获取每个发出的项目 (an Iterable<T>) 并将其作为Observable<T>
  2. flatMap获取每个发出的Observable<T>对象并将它们合并为一个Observable<T>

The Transformer looks like this:

变压器看起来像这样:

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);
            }
        });
    }
}

Once you've created your Transformer, you can use composeto apply the transformation on the source observable:

创建 Transformer 后,您可以使用compose将转换应用于源 observable:

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);
        }
    };
}

The advantage of using a composewith a Transformerinstead of a flatMapwith a Func1is that if in the future if you need to flatten a list again, you won't even have to think about which operator to use (map? flatMap? concatMap?). In other words, the flatmap operation is baked into the FlattenTransform class and that detail is abstracted away.

使用 a composewith aTransformer而不是 a flatMapwith a的好处Func1是,如果将来如果您需要再次展平列表,您甚至不必考虑使用哪个运算符(map?flatMap?concatMap?)。换句话说, flatmap 操作被烘焙到 FlattenTransform 类中,并且细节被抽象掉了。

Transformers also have other benefits, such as being able to chain together multiple operations.

Transformer 还具有其他好处,例如能够将多个操作链接在一起。

回答by Patrick Favre

As an alternative to flatMapIterableyou can do this with flatMap:

作为替代方案,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
}

Personally I think .flatMap(numberList -> Observable.fromIterable(numberList))is easier to read and understand than .flatMapIterable(numberList -> numberList ).

我个人认为.flatMap(numberList -> Observable.fromIterable(numberList)).flatMapIterable(numberList -> numberList ).

The difference seems to be the order (RxJava2):

区别似乎是顺序(RxJava2):

  • Observable.fromIterable:Converts an Iterable sequence into an ObservableSource that emits the items in the sequence.
  • Observable.flatMapIterable:Returns an Observable that merges each item emitted by the source ObservableSource with the values in an Iterable corresponding to that item that is generated by a selector.
  • Observable.fromIterable:将 Iterable 序列转换为 ObservableSource,以发出序列中的项目。
  • Observable.flatMapIterable:返回一个 Observable,它将源 ObservableSource 发出的每个项目与由选择器生成的项目对应的 Iterable 中的值合并。

Using method references this looks like:

使用方法引用这看起来像:

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

回答by CoolMind

In Kotlin use flattenAsFlowable:

在 Kotlin 中使用flattenAsFlowable

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