When the user types into the SearchView
widget, the app should make an
API call (in background thread) to fetch search results from server, and display them (in UI thread) in RecyclerView.
I use the following code in my fragment:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.my_fragment, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
RxSearchView.queryTextChanges(searchView)
.debounce(400, TimeUnit.MILLISECONDS)
.map(CharSequence::toString)
.switchMap(query -> retrofitService.search(query))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<Item>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.e(LOG_TAG, "Error", e);
}
@Override
public void onNext(List<Item> items) {
// adapter.addItems(...)
}
});
}
But I get an exception:
java.lang.IllegalStateException: Must be called from the main thread. Was: Thread[RxIoScheduler-2,5,main]
at com.jakewharton.rxbinding.internal.Preconditions.checkUiThread(Preconditions.java:35)
at com.jakewharton.rxbinding.support.v7.widget.SearchViewQueryTextChangesOnSubscribe.call(SearchViewQueryTextChangesOnSubscribe.java:18)
at com.jakewharton.rxbinding.support.v7.widget.SearchViewQueryTextChangesOnSubscribe.call(SearchViewQueryTextChangesOnSubscribe.java:10)
...
When I remove .subscribeOn(Schedulers.io())
, the search API call is fired when fragment is created and no query is typed in SearchView
and I get exeption
retrofit2.adapter.rxjava.HttpException: HTTP 422
then, when I type my search query retrofitService.search(query)
is no longer called.
Remember that you can actually use multiple
observeOn
and multiplesubscribeOn
operators in your rx chain.Try this:
This will basically result in this Thread usage:
I use such an approach on a production app.