3

I am using RxBinding in my current Android application and wish to implement a text search feature.

My code is as follows:-

compositeDisposable.add(RxTextView.textChangeEvents(searchEditText)
                .skipInitialValue()
                .subscribeOn(Schedulers.io())
                .debounce(200, TimeUnit.MILLISECONDS)
                .filter(textViewTextChangeEvent -> (textViewTextChangeEvent.text().length() == 0 || textViewTextChangeEvent.text().length() > 2))
                .map(event -> event.text().toString())
                .distinct()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(charactersResponse -> {
                    articlesLiveData = viewModel.textSearch(charactersResponse);
                    textLiveData.removeObserver(TextFragment.this);
                    textLiveData.observe(TextFragment.this, TextFragment.this);
                }));

I want to only search for distinct values, however the code above makes duplicate search requests.

Why isn't distinct removing duplicate strings?

For example when I type "chilean" into my Search EditText

my search code is called with the following strings

chi
chi
chil
chil
chil
chile
chile
chilea
chilean
chilean

What am I doing wrong?

Hector
  • 4,016
  • 21
  • 112
  • 211
  • 1
    Fragment or Activity? In what method are you making this subscription? onCreate? onStart? onViewCreated? – d370urn3ur Oct 29 '18 at 17:01
  • its in a Fragment, onViewCreated. What difference does it make where I set this up? everything works as required except for distinct() having no effect whatsoever. @d370urn3ur – Hector Oct 29 '18 at 20:01

1 Answers1

1

Without more context I can't really be sure but it seems like the subscription has been made twice. You said you put this code in Fragment::onViewCreated, so maybe you are loading another fragment and then coming back to this one without disposing of the first subscription? You can put a breakpoint where you make the subscription to see if it is getting called twice. If it only gets called once and you still have this problem I will need to see more of your code to diagnose it.

When I copy your code into Activity::onCreate it works as expected. So the first thing you can do is make sure you are disposing your compositeDisposable in Fragment::onDestroyView. That should fix the multiple-emission problem.

Now you will have another problem: you are using distinct(), but I doubt that's what you want from a search bar. Distinct will filter ALL non-unique values for the lifetime of the observable. So once it has emitted "chile", if you continue to type "chilean" and then erase "an", you will never see "chile" again. What you probably want is distinctUntilChanged(), which just filters out non-unique matches to the LAST emitted value.

d370urn3ur
  • 1,736
  • 4
  • 17
  • 24
  • Good spot, I was indeed binding the search edit text multiples times. now that I am only binding once my duplicate issue has been resolved. One thing I did notice was once I had got .distinct() and .distinctUntilChanged() working as desired, I generated many "Choreographer: Skipped 53 frames! The application may be doing too much work on its main thread." warnings event though I had .subscribeOn(Schedulers.computation()) @d370urn3ur – Hector Oct 30 '18 at 12:03