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
RxJava - fetch every item on the list
提问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 flatMapIterable
method for this case since it belongs to Iterable
as 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 flatMap
on it with a function. You can think of this as a 2-step process:
使用一个修改源 Observable的Transformer,flatMap
用一个函数调用它。您可以将其视为一个 2 步过程:
- The function takes each emitted item (an
Iterable<T>
) and re-emits it as anObservable<T>
flatMap
takes each of these emittedObservable<T>
objects an merges them into a singleObservable<T>
- 该函数获取每个发出的项目 (an
Iterable<T>
) 并将其作为Observable<T>
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 compose
to 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 compose
with a Transformer
instead of a flatMap
with a Func1
is 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 compose
with aTransformer
而不是 a flatMap
with 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 flatMapIterable
you 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) })