RxJava - 获取列表中的每一项
RxJava - fetch every item on the list
我有一个方法 returns 一个 Observable<ArrayList<Long>>
,它们是一些项目的 ID。我想浏览此列表并使用 returns 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<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>
使用修改源 Observable 的 Transformer,用函数调用 flatMap
。您可以将此视为一个两步过程:
- 该函数获取每个发出的项目(
Iterable<T>
)并将其作为 Observable<T>
重新发出
flatMap
获取每个发出的 Observable<T>
对象并将它们合并为一个 Observable<T>
变形金刚看起来像这样:
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);
}
});
}
}
创建转换器后,您可以使用 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);
}
};
}
使用 compose
和 Transformer
而不是 flatMap
和 Func1
的好处是,如果将来您需要展平列表同样,您甚至不必考虑使用哪个运算符(map?flatMap?concatMap?)。换句话说,平面图操作被烘焙到 FlattenTransform class 并且该细节被抽象掉了。
变形金刚还有其他好处,例如能够将多个操作链接在一起。
作为 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: Returns 一个 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) })
对于 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
})
我有一个方法 returns 一个 Observable<ArrayList<Long>>
,它们是一些项目的 ID。我想浏览此列表并使用 returns 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<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>
使用修改源 Observable 的 Transformer,用函数调用 flatMap
。您可以将此视为一个两步过程:
- 该函数获取每个发出的项目(
Iterable<T>
)并将其作为Observable<T>
重新发出
flatMap
获取每个发出的Observable<T>
对象并将它们合并为一个Observable<T>
变形金刚看起来像这样:
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);
}
});
}
}
创建转换器后,您可以使用 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);
}
};
}
使用 compose
和 Transformer
而不是 flatMap
和 Func1
的好处是,如果将来您需要展平列表同样,您甚至不必考虑使用哪个运算符(map?flatMap?concatMap?)。换句话说,平面图操作被烘焙到 FlattenTransform class 并且该细节被抽象掉了。
变形金刚还有其他好处,例如能够将多个操作链接在一起。
作为 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: Returns 一个 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) })
对于 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
})