如何在使用RxJava或Retrofit2消耗ApiRest的AutoCompleteTextView适配器中返回FilterResults?

时间:2017-07-29 04:53:05

标签: android rx-java retrofit2

我正在编写一个由ApiRest填充的autocompleteTextView适配器。我正在使用rxJava和Retrofit 2.但无法获得过滤结果,因为我不知道如何在异步函数中返回值。这是我的代码

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请求正常但无法返回值。

我的问题是如何返回过滤后的结果?

2 个答案:

答案 0 :(得分:0)

问题在于,您正在执行异步操作,其中API期望同步操作,这意味着您正在启动异步操作,而立即返回空FilterResults,异步操作没有&# 39; t坐下并等待结果,然后将其返回到performFiltering方法中,因此异步操作(Observer.onNext内部)的结果在您已经返回空{后发生变化} {1}}。

FilterResults对象是抽象类,已经在后台线程Filter method invoked in a worker thread上完成了实际工作的繁重工作,你应该在{i}的UI线程中处理结果{3}}方法。

此API不完全适合RxJava反应模型,您可以直接在performFiltering调用服务器调用并返回在工作线程中调用的结果。
如果你想要RxJava,你可以通过将流转换为阻塞流并返回结果来实现:

performFiltering

编辑:为什么你不应该在 @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执行请求将会有效,因为它是为您在获得结果后更新UI而设计的(可能会通知适配器),因此在您执行bg中的请求后,您将返回主线程并更新适配器。

但是,它会引入一些错误,因为您没有绑定到正确的过滤生命周期,这意味着进度指示会立即消失,并且在您实际在后台获取结果时不会显示,此外,更多的服务器问题,它会在多个请求被触发时导致错误,因为之前的请求可能会在稍后的请求之后到达并使用旧数据更新适配器。这就是为什么您需要遵守过滤器API并在publishResults以阻止方式执行请求的原因。

答案 1 :(得分:0)

您只需要调用notifyDataSetChanged()。它将更新结果。不要忘记初始化计数

@NonNull
@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            final FilterResults results = new FilterResults();
            if (constraint != null) {

                mCompositeDisposable.add(NetworkClient.getRetrofit().create(NetworkInterface.class)
                .getPredictions(MapHelper.makeAutocompleteURL((BaseActivity) context, location, constraint.toString(), Config.SEARCH_RADIUS * 1000))
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread()).subscribeWith(new DisposableObserver<PlaceSerializer>(){
                            @Override
                            public void onNext(PlaceSerializer placeSerializer) {
                                data = new ArrayList<Place>(placeSerializer.getPlaces());
                                results.values = data;
                                results.count = data.size();
                                notifyDataSetChanged();
                            }

                            @Override
                            public void onError(Throwable e) {
                                LogHelper.e(TAG, e.getMessage());
                            }

                            @Override
                            public void onComplete() {

                            }
                        }));

                results.values = data;
                results.count = data.size();
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results != null && results.count > 0) {
                notifyDataSetChanged();
            } else notifyDataSetInvalidated();
        }
    };
}