3

I am new to Rx world and try to implement my AutoCompleteTextView with RxJava, RxBinding and Retrofit 2.

Here's what I come up with which is troublesome: (Maybe I'm not doing it in the right way.)

I have an AutoCompleteTextView and here I created my subscribtion and observables:

subcription = RxTextView.textChangeEvents(clearableEditText)
                .skip(1)
                .debounce(400, TimeUnit.MILLISECONDS)
                .map(new Func1<TextViewTextChangeEvent, String>() {
                    @Override
                    public String call(TextViewTextChangeEvent textViewTextChangeEvent) {
                        return textViewTextChangeEvent.text().toString();
                    }
                })
                .filter(new Func1<String, Boolean>() {
                    @Override
                    public Boolean call(String s) {
                        return s.length() > 2;
                    }
                })
                .flatMap(new Func1<String, Observable<List<String>>>() {
                    @Override
                    public Observable<List<String>> call(String text) {
                        return searchService.getAutoCompleteTermsObservable(text)
                                .subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread());
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<List<String>>() {
                    @Override
                    public void onCompleted() {
                        Log.d("rx", "oncomplete");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e("rx", e.toString());
                    }

                    @Override
                    public void onNext(List<String> strings) {
                        Log.d("rx", strings.size()+"");
                        autoAdapter = new ArrayAdapter<>(MainActivity.this,
                                android.R.layout.simple_dropdown_item_1line, strings);
                        clearableEditText.setAdapter(autoAdapter);
                        clearableEditText.showDropDown();
                    }
                });

My issue is when I set my EditText with setText() method, it triggers dropdown. For example it does that when I set the word from AutoCompleteTextView's dropdown and when I set it with voice input. Is there a way to avoid triggering onTextChanged when I set it manually? Or how can I fix that?

Figen Güngör
  • 12,169
  • 14
  • 66
  • 108

1 Answers1

1

You could indeed use unsubscribe() but depending on how you set the value, you also use skipWhile. Here is an example:

public void handleTextChanges() {
    final String textFromSource = "an";

    Observable.fromArray("a", "an", "ancestor")
            .skipWhile(new Predicate<String>() {
                @Override
                public boolean test(String value) throws Exception {
                    return textFromSource.contains(value);
                }
            })
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String value) throws Exception {
                    Log.d("Rx", value);
                }
            });
}

This will only consume ancestor (example is RxJava2, but the same methods exist). Any subsequent values, even if they match an, will be consumed. You could use filter if you always want to do the check like this

Jordy Langen
  • 3,591
  • 4
  • 23
  • 32
  • Thanks for the alternative approach @Jordy Langen. However, doesn't this one make unnecassary network request? – Figen Güngör Nov 14 '16 at 19:57
  • Not as long as the first truthy value has been matched in `skipWhile` – Jordy Langen Nov 14 '16 at 20:01
  • When I select item from AutoComplete dropdown, it'll call setText with that value and because it triggers onTextChange, it'll make only one request to get autocomplete suggestions and with skipWhile, dropdown will not be shown. Same with voice input, I'll call setText, this time it may or may not match with that but also in these cases dropdown will not be shown. Yeah, actually, that approach seems like more clean than my setTextSafely() method. And I call this method in several places so if I wanna make autocomplete a user prefence, your way will give me flexibility. Thanks, @Jordy Langen – Figen Güngör Nov 14 '16 at 20:50
  • On a second thought, I can check that preference in my setTextSafely() method, too. =) – Figen Güngör Nov 14 '16 at 21:03