Мое текущее приложение для Android использует LiveData для заполнения моего recyclerView.
У некоторых пользователей есть тысячи элементов для отображения.
Я также разрешаю своим пользователям искать / фильтровать элементы, хранящиеся в recyclerView.
Первоначальное отображение списка в порядке.
Однако, когда пользователь начинает искать / фильтровать список от 1000 до 1 или 2 элементов, пользовательский интерфейс действительно становится очень плохим, пользовательский интерфейс перестает отвечать на запросы в течение 10 секунд.
Мой адаптер RecyclerView использует android.support.v7.util.DiffUtil для управления изменениями элементов списка.
Я попытался использовать RxJava в методе onChange моей активности для выполнения различий в фоновом потоке.
Observable.just(newItems)
.doOnSubscribe(compositeDisposable::add)
.subscribeOn(Schedulers.io())
.switchMap(new Function<List<ItemUI>, ObservableSource<DiffUtil.DiffResult>>() {
@Override
public ObservableSource<DiffUtil.DiffResult> apply(final List<ItemUI> itemUIs) {
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new GenericDiffUtilCallback<>(adapter.getCurrentItems(), newItems));
return Observable.just(diffResult);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<DiffUtil.DiffResult>() {
@Override
public void accept(final DiffUtil.DiffResult diffResult) {
adapter.updateList(diffResult, articles);
}
});
Мой адаптер up [метод dateList похож на этот
public void updateList(final DiffUtil.DiffResult diffResult, final List<ItemUI> newItems) {
this.items.clear();
this.items.addAll(newItems);
diffResult.dispatchUpdatesTo(this);
}
Я все еще вижу сообщения logcat, подобные этому
Choreographer: Skipped 200 frames! The application may be doing too much work on its main thread.
Какую ошибку я сделал, чтобы по-прежнему видеть пропущенные кадры?
Можно ли различать большие изменения списка и при этом иметь отзывчивый пользовательский интерфейс?
@pskink обрабатывает ли библиотека разбиения на страницы различение отображаемых элементов? особенно, когда количество отображаемых элементов резко меняется, например. от 0 до 5000 в миллисекундах?
количество загружаемых элементов примерно 10-30, не больше, для этого и нужна подкачка
Опубликованный код теоретически не должен выполнять diff в основном потоке.
Попробуйте следующее:
Observable.just(newItems)
.observeOn(Schedulers.io()) // <------------------------------------
.map(new Function<List<ItemUI>, DiffUtil.DiffResult>() {
@Override
public DiffUtil.DiffResult apply(final List<ItemUI> itemUIs) {
return DiffUtil.calculateDiff(
new GenericDiffUtilCallback<>(
adapter.getCurrentItems(), itemUIs));
}
})
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(compositeDisposable::add) // <------------------------
.subscribe(new Consumer<DiffUtil.DiffResult>() {
@Override
public void accept(final DiffUtil.DiffResult diffResult) {
adapter.updateList(diffResult, articles);
}
});
Вам действительно не нужен switchMap. Кроме того, если вы действительно хотите, чтобы это действие вступило в силу, вы должны переместить его как можно ниже, иначе позиция в исходном вопросе не повлияет на вычисление diff под ним.
Я бы также проверил, не возникли ли у вас непреднамеренно проблемы с потоками, такие как случаи, описанные в этот блог.
Редактировать:
Если вы меняете источник, вы можете использовать switchMap, но также можете использовать fromCallable:
.switchMap(itemUIs -> {
return Observable.fromCallable(() ->
DiffUtil.calculateDiff(new GenericDiffUtilCallback<>(
adapter.getCurrentItems(), itemUIs))
)
.subscribeOn(Schedulers.computation());
})
@akamokd Я думал, что мне понадобится switchMap, поскольку каждый раз, когда пользователь меняет текст поиска, мне нужно заменить текущий поиск следующим введенным поисковым термином, иначе я получаю разногласия по списку элементов моего адаптера
Ладно, на самом деле у вас есть что-то другое, кроме just. В этом случае да, вам нужен switchMap, но вам также нужно убедиться, что вы не блокируете сам switchMap с вычислением diff. Поместите разницу в fromCallable.
используйте библиотеку поддержки Google пейджинг