I want to make a standard search in my Android app, where I type in an EditText
, wait a bit until the user is done typing, and fire up a network request using Retrofit :
// make observable out of EditText
Observable<OnTextChangeEvent> textObs = WidgetObservable.text(searchText);
mSearchResultSubscription =
textObs
// wait until user has not typed for 350 milliseconds
.debounce(350, TimeUnit.MILLISECONDS)
// get the string the user typed
.map(OnTextChangeEvent::text)
.map(CharSequence::toString)
// start a new observable (from Retrofit)
.flatMap(
q ->
// try network call and return my data
MyRetrofitAPI.getService().search(q)
// if this fails, just return empty observable
.onErrorResumeNext(error -> {
Log.e("Error from retrofit: " + error.getLocalizedMessage());
return Observable.empty();
})
)
// if all is well, show the contents on the screen somehow
.observeOn(AndroidSchedulers.mainThread())
.subscribe(a -> {
mAdapter.setItems(a);
}
, error -> {
Log.e("Also error in outer observable: " + error.getLocalizedMessage());
}
);
Now, I have a testserver that takes the retrofit call and returns a list. When I type 'crash' the server executes some invalid code and errors, returning http status code 500, and some error html. So, the retrofit call fails.
I would think the outer Observable chain should not be effected by this. See my previous question: In RxJava, how to retry/resume on error, instead of completing the observable
But, the outer Observable also errors, causing the chain to terminate. The error is:
The current thread must have a looper!
Strange. Now I try without the .debounce()
and the same thing happens, server has an internal error, but the outer Observable does not error.
So what is it about .debounce()
that it does to threads that is causing this behaviour? And how can I work around it?