How to implement search feature with SearchView, Retrofit and RxJava (RxBindings)?

前端 未结 2 518
一生所求
一生所求 2020-12-28 09:50

When the user types into the SearchView widget, the app should make an API call (in background thread) to fetch search results from server, an

相关标签:
2条回答
  • 2020-12-28 10:23

    I use such an approach on a production app.

     RxSearchView.queryTextChanges(searchView)
                        .debounce(300, TimeUnit.MILLISECONDS)
                        .filter(new Predicate<String>() {
                            @Override
                            public boolean test(String text) throws Exception {
                                if (text.isEmpty()) {
                                    return false;
                                } else {
                                    return true;
                                }
                            }
                        })
                        .distinctUntilChanged()
                        .switchMap(new Function<String, ObservableSource<String>>() {
                            @Override
                            public ObservableSource<String> apply(String query) throws Exception {
                                return dataFromNetwork(query);
                            }
                        })
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Consumer<String>() {
                            @Override
                            public void accept(String result) throws Exception {
                                textViewResult.setText(result);
                            }
                        });
    
    • DistinctUntilChanged: The distinctUntilChanged operator is used to avoid the duplicate network calls. Let say the last on-going search query was “abc” and the user deleted “c” and again typed “c”. So again it’s “abc”. So if the network call is already going on with the search query “abc”, it will not make the duplicate call again with the search query “abc”. So, distinctUntilChanged suppress duplicate consecutive items emitted by the source Observable.
    • SwitchMap: Here, the switchMap operator is used to avoid the network call results which are not needed more for displaying to the user. Let say the last search query was “ab” and there is an ongoing network call for “ab” and the user typed “abc”. Then you are no more interested in the result of “ab”. You are only interested in the result of “abc”. So, the switchMap comes to the rescue. It only provides the result for the last search query(most recent) and ignores the rest.
    0 讨论(0)
  • Remember that you can actually use multiple observeOn and multiple subscribeOn operators in your rx chain.

    Try this:

    RxSearchView.queryTextChanges(searchView)
                .debounce(400, TimeUnit.MILLISECONDS)
                .map(CharSequence::toString)
                .subscribeOn(AndroidSchedulers.mainThread())
                .observeOn(Schedulers.io())
                .switchMap(query -> retrofitService.search(query))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<List<Item>>() {
                    @Override
                    public void onCompleted() {
    
                    }
    
                    @Override
                    public void onError(Throwable e) {
                        Log.e(LOG_TAG, "Error", e);
                    }
    
                    @Override
                    public void onNext(List<Item> items) {
                        // adapter.addItems(...)
                    }
                });
    

    This will basically result in this Thread usage:

    0 讨论(0)
提交回复
热议问题