web-dev-qa-db-ja.com

androidコンパレータクラスを含むrxjavaソートリスト

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) {

                    }
                });
11
okarakose

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>が個別に非同期で並べ替えられます。

14
Larry B.

このソリューションは受け入れられた回答に似ていますが、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を使用することをお勧めします。

13
Pär Nils Amsen

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.
                }
    });
_
7
Arun kumar

リストを並べ替える方法がもう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.
        });
5
aleksandrbel

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 ->
        //..
    }))
3
Dr.jacky

次のようにすることもできます:

Observable.from(list)
        .sorted((o1, o2) -> o1.name.compareTo(o2.name))
        .toList()
        .subscribe(
            sortedList -> sortedList,
            error -> error);

コトリン:

list.sortBy { it.name }
0
manmohan