いくつかのアイテムのIDであるObservable<ArrayList<Long>>
を返すメソッドがあります。このリストを調べて、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>
_
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.just(Arrays.asList(1, 2, 3))
.flatMap(Observable::fromIterable)
.flatMap(this::downloadFoo)
_
Transformer を使用して、ソースObservableを変更し、関数でflatMap
を呼び出します。これは2段階のプロセスと考えることができます。
Iterable<T>
)を受け取り、Observable<T>
として再発行しますflatMap
は、これらの放出されたObservable<T>
オブジェクトをそれぞれ取り、それらを単一のObservable<T>
にマージします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
を使用して、ソース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);
}
};
}
compose
でTransformer
をFunc1
の代わりにflatMap
で使用する利点は、将来リストをフラット化する必要がある場合、使用する演算子についても考える必要があります(map?flatMap?concatMap?)。つまり、flatmap操作はFlattenTransformクラスにベイクされ、その詳細は抽象化されます。
トランスフォーマーには、複数の操作を連結できるなど、他の利点もあります。
KotlinではflattenAsFlowable
を使用します。
repository.getFlowableData(id)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.computation())
.toList()
.flattenAsFlowable { it }
.map { someMethod(it) }
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ },
{ onError(it) })