I am coding an autocompleteTextView adapter which is filled by an ApiRest. I'm using rxJava and Retrofit 2. but cannot get the filtered result because i dont know how to return the value in asynchronous function. here is my code
public class DiagnosticoAutoCompleteAdapter extends BaseAdapter implements Filterable {
...
@Override
public Filter getFilter() {
Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
final FilterResults filterResults= new FilterResults();
if(charSequence!=null) {
ApiUtils.getAPIServiceDos()
.getDiagnosticos(charSequence.toString())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<Diagnostico>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(List<Diagnostico> value) {
// HERE IT SHOWS ME THE SIZE E.G. 45 so The values are received correctly
System.out.println("tamaño diagnostico::"+value.size());
// HERE IT SHOWS ME THE OBJECT NAME IN POSITION 0 AND ITS OK
System.out.println("contenido diagg...."+value.get(0).getNombre());
filterResults.values=value;
filterResults.count=value.size();
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
//here i lost the information. the count is 0
System.out.println("tamaño de filtered results::"+filterResults.count);
return filterResults;
}
The RxJava request works OK but cannot return the values.
My question is how to return the filtered results??
You need to just call notifyDataSetChanged(). It will update the result. Don't forget to initialise values and count.
The problem is that you're performing asynchronous operation where the API expected synchronous one, meaning you're launching a the async operation, while returning immediately the empty
FilterResults
, the async operation didn't sits and wait to the result before returning it back inside theperformFiltering
method, thus the result from the async operation (inside theObserver.onNext
) is changed after you've already return emptyFilterResults
.Filter
object is abstract class that already do the heavy lifting of doing the actual work on background thread,performFiltering
method invoked in a worker thread, and you should handle the results in the UI thread at publishResults method.This API is not exactly fits to RxJava reactive model, you can invoke the server call directly at
performFiltering
and return the result as it's invoked in a worker thread.If you want RxJava, you can do it by converting the stream to a blocking one and returns the result:
EDIT: Why you should not fire the async request at
publishResults
:performing the request at
publishResults
will work as it's designed for you to update the UI after you have the results (probably notify the adapter), so after you perform the request in bg you return to main thread and update the adapter.BUT, it will introduce some bugs, as you're not bound to the correct lifecycle of filtering, that means that the progress indication will disappear immediately, and will not shown while you actually fetch the result in the background, additionally, more sever problem, it will cause bugs when multiple requests are fired, as earlier request might arrive after later one and update the adapter with old data. that's why you need to obey the filter API and perform the request in blocking fashion at the
performFiltering
.