如何使用 RxJava 或 Retrofit2 在使用 ApiRest 的 AutoCompleteTextView Adapter 中返回 FilterResults? [英] How to return FilterResults in AutoCompleteTextView Adapter consuming ApiRest with RxJava or Retrofit2?
问题描述
我正在编写一个由 ApiRest 填充的 autocompleteTextView 适配器.我正在使用 rxJava 和 Retrofit 2. 但无法获得过滤结果,因为我不知道如何在异步函数中返回值.这是我的代码
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;
}
RxJava 请求工作正常,但无法返回值.
The RxJava request works OK but cannot return the values.
我的问题是如何返回过滤后的结果??
My question is how to return the filtered results??
推荐答案
问题是您正在执行异步操作,而 API 预期是同步操作,这意味着您正在启动异步操作,同时立即返回空 FilterResults
,异步操作并没有坐等结果,然后将其返回到 performFiltering
方法中,因此异步操作的结果(在 Observer 中).onNext
) 在您已经返回空的 FilterResults
之后发生变化.
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 the performFiltering
method, thus the result from the async operation (inside the Observer.onNext
) is changed after you've already return empty FilterResults
.
Filter
对象是抽象类,它已经完成了在后台线程上进行实际工作的繁重工作,performFiltering
在工作线程中调用的方法,你应该在UI线程中处理结果在 publishResults 方法.
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.
此 API 并不完全适合 RxJava 反应式模型,您可以直接在 performFiltering
处调用服务器调用,并返回在工作线程中调用的结果.
如果你想要 RxJava,你可以通过将流转换为阻塞流并返回结果来实现:
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:
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
final FilterResults filterResults = new FilterResults();
if (charSequence != null) {
List<Diagnostico> value = ApiUtils.getAPIServiceDos()
.getDiagnosticos(charSequence.toString())
.toBlocking()
.first();
System.out.println("tamaño diagnostico::" + value.size());
System.out.println("contenido diagg...." + value.get(0).getNombre());
filterResults.values = value;
filterResults.count = value.size();
}
return filterResults;
}
为什么不应该在 publishResults
触发异步请求:
Why you should not fire the async request at publishResults
:
在 publishResults
执行请求将起作用,因为它是为您设计的,在您获得结果后更新 UI(可能通知适配器),因此在 bg 中执行请求后,您将返回主线程并更新适配器.
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.
但是,它会引入一些错误,因为您没有绑定到正确的过滤生命周期,这意味着进度指示将立即消失,并且不会在您在后台实际获取结果时显示,此外,更严重的问题,当多个请求被触发时会导致错误,因为较早的请求可能会在较晚的请求之后到达并使用旧数据更新适配器.这就是为什么您需要遵守过滤器 API 并在 performFiltering
处以阻塞方式执行请求.
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
.
这篇关于如何使用 RxJava 或 Retrofit2 在使用 ApiRest 的 AutoCompleteTextView Adapter 中返回 FilterResults?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!