» » » Реализация поиска с использованием RxJava

 

Реализация поиска с использованием RxJava

Автор: admin от 23-12-2017, 23:45, посмотрело: 309

В данной статье будет рассмотрена оптимальная и компактная реализация поиска с использованием RxJava для Android, отсеивающая ненужные результаты и уменьшающая количество бесполезных сетевых вызовов.



Реализация поиска с использованием RxJava

Оригинал написан 16 октября 2017. Перевод вольный.

эту статью
  • Filter

  • Debounce

  • DistinctUntilChanged

  • SwitchMap



  • Начнем



    Сначала нужно сделать SearchView observable. Сделаем его с использованием PublishSubject. Я использую SearchView из Android. View может быть любым, с функционалом как у EditText. Для реализации observable нужно реализовать listener для изменения текста в поле.



    public class RxSearchObservable {
    
        public static Observable<String> fromView(SearchView searchView) {
    
            final PublishSubject<String> subject = PublishSubject.create();
    
            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String s) {
                    subject.onComplete();
                    return true;
                }
    
                @Override
                public boolean onQueryTextChange(String text) {
                    subject.onNext(text);
                    return true;
                }
            });
    
            return subject;
        }
    
    Замечание от ConstOrVar:

    Observable для SearchView будет не совсем корректно работать. Вы на него подписываетесь в onCreate(), но при срабатывании onQueryTextSubmit() произойдет отписка, так как вызовется onComplete. Получается, что повторный поиск не будет работать. Чтобы повторный поиск работал, нужно избавиться от subject.onComplete();

    Замечание от Scrobot и BFS:

    Не стоит использовать Subject, он существует только для 1 цели: соединять императивный стиль с реактивным. Лучше использовать Observable.create(). Поиск это ровно тот кейс, когда нужно думать о Backpressure, а поскольку практически все сегодня используют RxJava2, то там эта проблема решена с помощью Flowable, и лучше этот кейс зарефакторить на него.

    Далее необходимо вызвать созданный метод и добавить вызовы операторов, как в примере ниже.



    RxSearchObservable.fromView(searchView)
                    .debounce(300, TimeUnit.MILLISECONDS)
                    .filter(new Predicate<String>() {
                        @Override
                        public boolean test(String text) throws Exception {
                            if (text.isEmpty()) {
                                return false;
                            } else {
                                return true;
                            }
                        }
                    })
                    .distinctUntilChanged()
                    .switchMap(new Function<String, ObservableSource<String() {
                        @Override
                        public ObservableSource<String> apply(String query) throws Exception {
                            return dataFromNetwork(query);
                        }
                    })
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<String>() {
                        @Override
                        public void accept(String result) throws Exception {
                            textViewResult.setText(result);
                        }
                    });
    


    Теперь обсудим почему используются именно эти операторы и как они работают вместе.



    Debounce



    Этому оператору передаются параметры времени. В данном случае он отлавливает события ввода пользователем текста, например, «a», «ab», «abc». Ввод часто происходит очень быстро и это чревато большим количеством сетевых вызовов. Но пользователь обычно заинтересован только в результатах для «abc». Итак, нужно отбросить выполнение запросов для «a», «ab». Оператор debounce спешит на помощь. Он ожидает бездействия пользователя в течение переданного в параметре времени. Если во время ожидания будет осуществлен какой-либо ввод, то счётчик ожидания сбросится, отсчет начнется заново, предыдущий переданный результат, например, «a» будет отброшен. Таким образом, оператор debounce передает дальше по цепочке только те элементы, которые продержались без вызова новых событий в течение указанного времени ожидания.

    Реализация поиска с использованием RxJava



    Filter



    Данный оператор используется для отсеивания нежелательных строк, например, пустой строки, чтобы избежать ненужных сетевых вызовов.



    DistinctUntilChanged



    Данный оператор используется для того, чтобы избежать дублирования сетевых вызовов. Например, последний поисковой запрос был «abc», затем пользователь удалил «c» и заново ввел «c». Результат снова «abc». Если сетевой вызов уже в процессе с тем же параметром, то оператор distinctUntilChanged не даст осуществить аналогичный вызов повторно. Таким образом, оператор distinctUntilChanged отсеивает повторяющиеся последовательно переданные ему элементы.

    Реализация поиска с использованием RxJava



    SwitchMap



    В данном примере этот оператор используется для исключения сетевых вызовов, результаты которых больше не нужно показывать пользователю. Например, последним поисковым запросом был «ab» и есть работающий сетевой вызов для этого запроса, но пользователь в это время вводит «abc». Результат для «ab» больше не нужен, нужен только результат для «abc». SwitchMap спешит на помощь. Он передает дальше результаты только последнего запроса, игнорируя остальные.



    Javadoc описывает switchMap следующим образом:



    Возвращает новый Observable, применяя переданную функцию для каждого полученного элемента Observable, но передавая далее элементы, созданные только последним полученным Observable.



    Мы сделали это! Только представьте насколько было бы сложно реализовать поиск без RxJava.



    Если вы хотите рассмотреть полный пример, то взгляните на следующий проект.

    Источник: Хабрахабр

    Категория: Операционные системы » Android

    Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
    Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

    Добавление комментария

    Имя:*
    E-Mail:
    Комментарий:
    Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
    Введите два слова, показанных на изображении: *