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?
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