与 android 的搜索功能中使用的 Rx-Java 一起使用时,如何停止多次改造调用?

How stop multiple retrofit calls when using it with Rx-Java used in search functionality for android?

我的 Android 应用程序中有搜索功能。 searchView 有回调 onSearchTextChanged(String oldQuery, String newQuery)。每次用户在搜索字段中输入任何文本时都会调用此回调函数。我在此回调中有一个 REST 调用,每次输入每个单词时都会触发该调用。这导致多次调用 REST。我想避免这种情况。我只希望一次只激活一个实例,这是最新的一个实例,并且只要键入新字母,所有其他调用都应立即取消。以下是代码详情。

 @Override
    public void onSearchTextChanged(String oldQuery, String newQuery) {

        floatingSearchView.showProgress();
        moviesAPI.searchQuery(newQuery)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Search>() {
                               @Override
                               public void onCompleted() {
                                   Log.d(TAG, "onCompleted() called");
                               }

                               @Override
                               public void onError(Throwable e) {
                                   Log.d(TAG, "onError() called with: e = [" + e + "]");
                               }

                               @Override
                               public void onNext(Search search) {
                                   floatingSearchView.hideProgress();
                                   floatingSearchView.swapSuggestions(search.getSearchResults());
                                   Log.d(TAG, "onNext() called with: search = [" + search + "]");
                               }
                           }

                );

    }

您可能希望在键入时使用去抖来延迟搜索请求(并且仅在用户停止键入 x 持续时间之后)。

此外,为了在新请求到达时取消旧请求,您可以将文本更改事件转换为事件流(手动或使用 RxBindings 之类的库),然后切换映射每个新文本事件以进行查询。 当新的搜索文本流驱动新请求到达时,switchMap 运算符将取消之前仍在进行的请求。

您可以找到各种使用 rxjava 实现 android 搜索建议的示例,例如 Kaushik Gopal 的示例:instantauto-searching-text-listeners-using-subjects--debounce

代码示例,此示例使用 RxBinding 库轻松获取 textChanages 事件作为 Observable 流。

RxTextView.textChangeEvents(tv)
                .debounce(300, TimeUnit.MILLISECONDS)
                .switchMap(new Func1<TextViewTextChangeEvent, Observable<SearchResult>>() {
                    @Override
                    public Observable<SearchResult> call(
                            TextViewTextChangeEvent textViewTextChangeEvent) {
                        return moviesAPI.searchQuery(textViewTextChangeEvent.text().toString())
                                .subscribeOn(Schedulers.io());
                    }
                })
                .subscribe(new Subscriber<SearchResult>() {
                    @Override
                    public void onCompleted() {
                        Log.d(TAG, "onCompleted() called");
                    }

                    @Override
                    public void onError(Throwable e) {
                        floatingSearchView.hideProgress();
                        Log.d(TAG, "onError() called with: e = [" + e + "]");
                    }

                    @Override
                    public void onNext(SearchResult search) {
                        floatingSearchView.hideProgress();
                        floatingSearchView.swapSuggestions(search.getSearchResults());
                        Log.d(TAG, "onNext() called with: search = [" + search + "]");
                    }
                });