Как использовать android.support.v7.util.DiffUtil с RxJava, LiveData и не создавать пропущенные ### кадры - PullRequest
0 голосов
/ 01 ноября 2018

Мое текущее приложение для Android использует LiveData для заполнения моего recyclerView.

У некоторых пользователей есть 1000 элементов для отображения.

Я также разрешаю своим пользователям искать / фильтровать элементы, хранящиеся в программе recyclerView.

Начальное отображение списка в порядке.

Однако, когда пользователь начинает искать / фильтровать список от 1000 до 1 или 2 элементов, UX действительно становится очень плохим, и пользовательский интерфейс перестает отвечать на запросы в течение 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);

            }
        });

Мой адаптер вверх [метод 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.

Какую ошибку я совершил, увидев пропущенные кадры?

Можно ли анализировать большие изменения списка и при этом иметь отзывчивый интерфейс?

1 Ответ

0 голосов
/ 04 ноября 2018

Теоретически размещенный код не должен выполнять 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. Также, если вы действительно хотите, чтобы это распоряжение вступило в силу, вы должны переместить его как можно ниже, в противном случае позиция в исходном вопросе не повлияет на вычисление различий под ним.

Я бы также проверил, не случайно ли вы столкнулись с проблемами многопоточности, такими как случаи, описанные в этом блоге

Изменить:

Если вы меняете источник, вы можете использовать switchMap, но также использовать fromCallable:

    .switchMap(itemUIs ->  {
        return Observable.fromCallable(() ->
            DiffUtil.calculateDiff(new GenericDiffUtilCallback<>(
                adapter.getCurrentItems(), itemUIs))
        )
        .subscribeOn(Schedulers.computation());
    })
...