Androidプロジェクトでrxjavaを使い始めました。API呼び出しから返されるイベントリストを並べ替える必要があります。リストを並べ替えるコンパレータクラスを記述しました:
public class EventParticipantComparator {
public static class StatusComparator implements Comparator<EventParticipant> {
@Override
public int compare(EventParticipant participant1, EventParticipant participant2) {
return participant1.getStatus() - participant2.getStatus();
}
}
}
このクラスをクラシックコレクションクラスで使用できます。
Collections.sort(participants, new EventParticipantComparator.StatusComparator());
どうすればこの状況を反応的な方法で達成できますか? リストを非同期にソートする方法がある場合も、その方法を優先します。
リストをソートしない反応的な方法:
dataManager.getEventImplementer().getParticipants(event.getId())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<EventParticipant>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(List<EventParticipant> eventParticipants) {
}
});
Collections.sort()
のJavadocを読んでいなかった場合、変換するには map
(list -> Collections.sort (list, comparator))
のようなものをお勧めしますソートされた配列に。ここで、map
は監視可能なマッパーです。
ただし、上記のsort
メソッドはインプレースソートアルゴリズムであり、完全にソートされた配列を返すのではなく、基になる配列に影響を与えます。したがって、代わりに次のようなことを行う必要があります。
dataManager.getEventImplementer().getParticipants(event.getId())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(unsortedList -> {
List<EventParticipant> sortedList = new ArrayList<>(unsortedList);
Collections.sort(sortedList, new EventParticipantComparator.StatusComparator());
return sortedList;
})
.subscribe(new Subscriber<List<EventParticipant>>() {
// ... etc.
});
これにより、各着信List<EventParticipant>
が個別に非同期で並べ替えられます。
このソリューションは受け入れられた回答に似ていますが、Rx演算子を使用して1)配列をオブジェクトに分割します2)インスタンスでソートします比較可能な実装3)専用の計算スレッドで実行します。
dataManager.getEventImplementer().getParticipants(event.getId())
.flatMap(Observable::from)
.toSortedList()
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(sortedList -> {...}, error -> {...});
ネットワーク/ディスクの書き込みにはSchedulers.ioを、ソートなどの計算にはSchedulers.computationを使用することをお勧めします。
getParticipants()
メソッドが_Observable<List<EventPartcipant>>
_を返すと想定しています。
以下のスニペットでは、最初にflatMap()
演算子を使用して_Observable<List<EventPartcipant>>
_を_Observable<EventParticipant>
_に変換します。このオブザーバブルは、一度に1つずつEventParticipant
を発行します。ここで、toSortedList()
演算子を使用することで、_Comparator<EventParticipant>::compareTo
_が期待するように、一度に2つのEventParticipant
オブジェクトを操作できます。
他のソリューションでは、並べ替え演算子は.observeOn(AndroidSchedulers.mainThread())
の後に適用されます。これは、実際の並べ替えがUIスレッドで行われることを意味します。
これを変更して、API呼び出しをIOスケジューラーで実行し、計算スケジューラーでソートし、最後にUIスレッドでソートしたリストを実行できるようにしました。
_getParticipants().flatMap(new Func1<List<EventParticipant>, Observable<EventParticipant>>() {
@Override
public Observable<EventParticipant> call(List<EventParticipant> eventParticipants) {
return Observable.from(eventParticipants);
}
}).subscribeOn(Schedulers.io())
.observeOn(Schedulers.computation())
.toSortedList(new Func2<EventParticipant, EventParticipant, Integer>() {
@Override
public Integer call(EventParticipant eventParticipant, EventParticipant eventParticipant2) {
return new StatusComparator().compare(eventParticipant, eventParticipant2);
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<EventParticipant>>() {
@Override
public void call(List<EventParticipant> eventParticipants) {
// Your sorted list on UI thread.
}
});
_
リストを並べ替える方法がもう1つあります
dataManager.getEventImplementer().getParticipants(event.getId())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMapIterable(participants -> participants)
.toSortedList((p1,p2) -> {p1.getStatus() - p2.getStatus()})
.subscribe(new Subscriber<List<EventParticipant>>() {
// ... etc.
});
Kotlinバージョン:
disposable.add(interactor.getItemList() //It returns Observable<ItemListResponseModel>
.compose(threadTransformer.applySchedulers())
.flatMapIterable { list -> list }
.toSortedList { p1, p2 ->
(p1?.name ?: "").compareTo(p2?.name ?: "")
}
.subscribe({ items ->
//...
}, { throwable ->
//..
}))
次のようにすることもできます:
Observable.from(list)
.sorted((o1, o2) -> o1.name.compareTo(o2.name))
.toList()
.subscribe(
sortedList -> sortedList,
error -> error);
コトリン:
list.sortBy { it.name }