Список сортировки android rxjava с классом компаратора
Я начал использовать rxjava с моими проектами Android. Мне нужно отсортировать список событий из вызова 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.
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) {
}
});
Ответы
Ответ 1
Если бы я не читал Javadoc для Collections.sort()
, я бы рекомендовал нечто вроде 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>
индивидуально и асинхронно.
Ответ 2
Это решение похоже на принятый ответ, но использует операторы 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 для вычислений, таких как сортировка
Ответ 3
Я предполагаю, что метод getParticipants()
возвращает Observable<List<EventPartcipant>>
.
В приведенном ниже фрагменте я сначала конвертирую Observable<List<EventPartcipant>>
в Observable<EventParticipant>
с помощью оператора flatMap()
. Этот наблюдаемый будет излучать каждый EventParticipant
по одному за раз. Теперь, используя оператор toSortedList()
, я могу воздействовать на два объекта EventParticipant
одновременно, как ожидается, Comparator<EventParticipant>::compareTo
.
В других решениях операторы сортировки применяются после .observeOn(AndroidSchedulers.mainThread())
, что означает, что фактическая сортировка происходит в потоке пользовательского интерфейса.
Я изменил это, чтобы вызов API выполнялся в планировщике ввода-вывода, сортировки в планировщике вычислений и, наконец, ваш отсортированный список в потоке пользовательского интерфейса.
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.
}
});
Ответ 4
Существует также еще один способ сортировки списка
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
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 ->
//..
}))