Фильтр Observable‹List› с текстом из EditText с использованием RxBinding

У меня есть массив объектов, и я хочу отфильтровать этот массив на основе типов текстовых пользователей в представлении EditText android.

Я подумал, что должен попытаться преобразовать массив POJO в Observable of Strings, и вот что я сделал:

    Observable<String> professionsObservable = Observable.fromArray(((GetStartedActivity) getActivity()).professions)
            .map(profession -> {
                if (profession.getName().length() > 0) {
                    professionsNameList.add(capitalizeFirstLetter(profession.getName()));
                }

                return professionsNameList;
            })
            .flatMapIterable(items -> items);

Теперь я хочу объединить текст из EditText с `professionsObservable, который я разместил выше.

Это код, который я использую:

    RxTextView.textChangeEvents(etProfession)
            .doOnEach(notif -> {
                if (etProfession.getText().toString().trim().length() > 0) {
                    etCompany.setVisibility(GONE);
                    etIndustry.setVisibility(GONE);
                } else {
                    etCompany.setVisibility(VISIBLE);
                    etIndustry.setVisibility(VISIBLE);
                }
            })
            .debounce(EDITTEXT_DELAY, TimeUnit.MILLISECONDS)
            .skip(1)
            .map(textChangeEvent -> textChangeEvent.text().toString())
            .switchMap(search -> {
                return professionsObservable
                        .filter(profession -> {
                            return profession.toLowerCase().startsWith(search);
                        });
                    }
            )
            .toList()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    filteredProfessions -> {
                        Timber.i("NOT ENTERING");
                        rvProfession.setVisibility(VISIBLE);
                        professionAdapter.addItems(filteredProfessions);
                    },
                    throwable -> Log.i("THROW", "PROFESSIONS ", throwable));

Я использую оператор map, чтобы преобразовать событие изменения текста в строку, а затем для каждой строки, которую я получаю из потока, я использую switchMap (потому что меня не интересуют результаты предыдущих поисков). Затем я составляю все строки в список с помощью toList. Проблема в том, что он никогда не достигает вызова subscribe, в то время как у меня есть много строк в исходном массиве, который я использовал, и я набираю текст, который соответствует условию оператора filter.

Это что-то, что я мог пропустить здесь?

РЕДАКТИРОВАТЬ: я обновил свой код до:

        RxTextView.textChangeEvents(etProfession)
            .doOnEach(notif -> {
                if (etProfession.getText().toString().trim().length() > 0) {
                    etCompany.setVisibility(GONE);
                    etIndustry.setVisibility(GONE);
                } else {
                    etCompany.setVisibility(VISIBLE);
                    etIndustry.setVisibility(VISIBLE);
                }
            })
            .subscribeOn(AndroidSchedulers.mainThread())
            .debounce(EDITTEXT_DELAY, TimeUnit.MILLISECONDS)
            .skip(1)
            .map(textChangeEvent -> textChangeEvent.text().toString())
            .flatMap(search -> {
                return Observable.fromArray(((GetStartedActivity) getActivity()).professions)
                        .map(profession -> {
                            List<String> professionsList = new ArrayList<>();
                            if (profession.getName().length() > 0) {
                                professionsList.add(capitalizeFirstLetter(profession.getName()));
                            }
                            return professionsList;
                        })
                        .flatMapIterable(items -> items)
                        .filter(profession -> {
                            if (profession.toLowerCase().startsWith(search.toLowerCase())) {
                            }

                            return profession.toLowerCase().startsWith(search.toLowerCase());
                        });
            })
            .toList()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    filteredProfessions -> {
                        rvProfession.setVisibility(VISIBLE);
             //        professionAdapter.addItems(filteredProfessions);
                    },
                    throwable -> Log.i("THROW", "PROFESSIONS ", throwable));

Если я удаляю оператор toList(), мой код работает (входит в вызов subscribe), но если я оставляю его там, он не работает. Кто-нибудь знает, почему?


person Mes    schedule 18.01.2018    source источник
comment
Неважно, я нашел ответ здесь   -  person Mes    schedule 18.01.2018


Ответы (1)


По моему опыту, RxBinding требует .subscribeOn(AndroidSchedulers.mainThread()) сразу после .textChangeEvents() или любого другого события. Так что, вероятно, вы вызываете сбой, добавляя .subscribeOn(Schedulers.io)

См. метод .checkMainThread() в https://github.com/JakeWharton/RxBinding/blob/master/rxbinding/src/main/java/com/jakewharton/rxbinding2/internal./Preconditions.java

ОБНОВЛЕНИЕ

Кроме того, вероятно, поскольку .onComplete() никогда не поступает из восходящего потока, .toList() никогда не выполняется.

person Maxim Volgin    schedule 18.01.2018
comment
Я сделал то, что вы сказали, но все тот же результат. Я также веду журнал в случае исключения, поэтому я думаю, что если бы был IllegalStateException, я бы увидел его в logcat. - person Mes; 18.01.2018
comment
Ах, тогда это, вероятно, потому, что .onComplete() никогда не исходит из восходящего потока, .toList() никогда не выполняется. - person Maxim Volgin; 18.01.2018