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?
Adding to pturner's answer, the Scheduler can be passed as
.debounce(400, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
This will cause the observer to work on the Main thread (UI thread) of Android, and will prevent Observer from throwing error.
Seems like the issue may be with debounce creating a new thread for the code to execute, from the docs:
This variant operates by default on the computation Scheduler, but you can optionally pass in a Scheduler of your choosing as a third parameter.
You might need to pass in an Android scheduler with a background Looper which would solve the error (in theory, unfortunately can't run your stuff right now without the server).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With