国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android仿淘寶搜索聯想功能的示例代碼

2019-10-22 18:29:07
字體:
來源:轉載
供稿:網友

現在不少應用都提供了搜索功能,有些還提供了搜索聯想。對于一個搜索聯想功能,最基本的實現流程為:客戶端通過監聽輸入框內容的變化,當輸入框發生變化之后就會回調afterTextChanged方法,客戶端利用當前輸入框內的文字向服務器發起請求,服務器返回與該搜索文字關聯的結果給客戶端進行展示。服務器那邊,一般要做內存緩存池,就是把有可能的結果都放在內存中。

效果圖

Android仿淘寶搜索,Android,搜索聯想功能,仿淘寶搜索功能

APP這邊也有幾個重要的問題需要我們思考

  • 當搜索詞為空時,不應該發起網絡請求。
  • 在用戶連續輸入的情況下,可能會發起某些不必要的請求。例如用戶輸入了abc,那么按照上面的實現,客戶端就會發起a、ab、abc三個請求。
  • 如果用戶依次輸入了ab和abc,那么首先會發起關鍵詞為ab請求,之后再發起abc的請求,但是abc的請求如果先于ab的請求返回,那么就會造成用戶期望搜索的結果為abc,但是我們最終希望得到的結果卻是和ab關聯的。

我的方案是采用retrofit2+rxjava2來實現的,針對這幾個問題的大致思路如下,關于這幾個操作符的解釋,在Demo中有較完整的解釋

  • 使用debounce操作符,當輸入框發生變化時,不會立刻將事件發布出去,而是等待200ms,如果在這段事件內,輸入框沒有發生變化,那么才發送該事件;反之,則在收到新的關鍵詞后,繼續等待200ms。
  • 使用filter操作符,只有關鍵詞的長度大于0時才把事件發布出去。filter作用:對源Observable產生的結果按照指定條件進行過濾,只有滿足條件的結果才會提交給訂閱者
  • 使用switchMap操作符,這樣當發起了abc的請求之后,即使ab的結果返回了,也不會發送給下游,從而避免了出現前面介紹的搜索詞和聯想結果不匹配的問題。switchMap操作符會保存最新的Observable產生的結果而舍棄舊的結果。

下面貼出關鍵代碼

 private void initEdt() {    editText = (EditText) findViewById(R.id.edt);    editText.addTextChangedListener(new TextWatcher() {      @Override      public void beforeTextChanged(CharSequence s, int start, int count, int after) {      }      @Override      public void onTextChanged(CharSequence s, int start, int before, int count) {      }      @Override      public void afterTextChanged(Editable s) {        if (s.toString().trim().isEmpty()) {          mPop.dismiss();        } else {          //輸入內容非空的時候才開始搜索          startSearch(s.toString());        }      }    });    mPublishSubject = PublishSubject.create();    mPublishSubject.debounce(200, TimeUnit.MILLISECONDS) //這里我們限制只有在輸入字符200毫秒后沒有字符沒有改變時才去請求網絡,節省了資源        .filter(new Predicate<String>() { //對源Observable產生的結果按照指定條件進行過濾,只有滿足條件的結果才會提交給訂閱者          @Override          public boolean test(String s) throws Exception {            //當搜索詞為空時,不發起請求            return s.length() > 0;          }        })        /**         * flatmap:把Observable產生的結果轉換成多個Observable,然后把這多個Observable         “扁平化”成一個Observable,并依次提交產生的結果給訂閱者         *concatMap:操作符flatMap操作符不同的是,concatMap操作符在處理產生的Observable時,         采用的是“連接(concat)”的方式,而不是“合并(merge)”的方式,         這就能保證產生結果的順序性,也就是說提交給訂閱者的結果是按照順序提交的,不會存在交叉的情況         *switchMap:與flatMap操作符不同的是,switchMap操作符會保存最新的Observable產生的         結果而舍棄舊的結果         **/        .switchMap(new Function<String, ObservableSource<String>>() {          @Override          public ObservableSource<String> apply(String query) throws Exception {            return getSearchObservable(query);          }        })        .observeOn(AndroidSchedulers.mainThread())        .subscribe(new DisposableObserver<String>() {          @Override          public void onNext(String s) {            //顯示搜索聯想的結果            showSearchResult(s);          }          @Override          public void onError(Throwable throwable) {          }          @Override          public void onComplete() {          }        });    mCompositeDisposable = new CompositeDisposable();    mCompositeDisposable.add(mCompositeDisposable);  }  //開始搜索  private void startSearch(String query) {    mPublishSubject.onNext(query);  }  private Observable<String> getSearchObservable(final String query) {    return Observable.create(new ObservableOnSubscribe<String>() {      @Override      public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {        Log.d(TAG, "開始請求,關鍵詞為:" + query);        try {          Thread.sleep(100); //模擬網絡請求,耗時100毫秒        } catch (InterruptedException e) {          if (!observableEmitter.isDisposed()) {            observableEmitter.onError(e);          }        }        if (!(query.contains("科") || query.contains("耐") || query.contains("七"))) {          //沒有聯想結果,則關閉pop          mPop.dismiss();          return;        }        Log.d("SearchActivity", "結束請求,關鍵詞為:" + query);        observableEmitter.onNext(query);        observableEmitter.onComplete();      }    }).subscribeOn(Schedulers.io());  }

下面是針對幾個操作符,從官網download下來的東西,供大家一起學習

debounce

Android仿淘寶搜索,Android,搜索聯想功能,仿淘寶搜索功能

debounce原理類似于我們在收到請求之后,發送一個延時消息給下游,如果在這段延時時間內沒有收到新的請求,那么下游就會收到該消息;而如果在這段延時時間內收到來新的請求,那么就會取消之前的消息,并重新發送一個新的延時消息,以此類推。

而如果在這段時間內,上游發送了onComplete消息,那么即使沒有到達需要等待的時間,下游也會立刻收到該消息。

filter

Android仿淘寶搜索,Android,搜索聯想功能,仿淘寶搜索功能

filter的原理很簡單,就是傳入一個Predicate函數,其參數為上游發送的事件,只有該函數返回true時,才會將事件發送給下游,否則就丟棄該事件。

switchMap

Android仿淘寶搜索,Android,搜索聯想功能,仿淘寶搜索功能

switchMap的原理是將上游的事件轉換成一個或多個新的Observable,但是有一點很重要,就是如果在該節點收到一個新的事件之后,那么如果之前收到的時間所產生的Observable還沒有發送事件給下游,那么下游就再也不會收到它發送的事件了。
如上圖所示,該節點先后收到了紅、綠、藍三個事件,并將它們映射成為紅一、紅二、綠一、綠二、藍一、藍二,但是當藍一發送完事件時,綠二依舊沒有發送事件,而最初綠色事件在藍色事件之前,那么綠二就不會發送給下游。

  • flatmap:把Observable產生的結果轉換成多個Observable,然后把這多個Observable“扁平化”成一個Observable,并依次提交產生的結果給訂者
  • concatMap:flatMap操作符不同的是,concatMap操作符在處理產生的Observable時,采用的是“連接(concat)”的方式,而不是“合并(merge)”的方式,這就能保證產生結果的順序性,也就是說提交給訂閱者的結果是按照順序提交的,不會存在交叉的情況
  • switchMap:與flatMap操作符不同的是,switchMap操作符會保存最新的Observable產生的結果而舍棄舊的結果

GitHub地址(完整Demo,歡迎下載)
https://github.com/zhouxu88/SearchDemo

rxjava2學習地址
https://github.com/ReactiveX/RxJava

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 葵青区| 太湖县| 靖宇县| 黎川县| 开平市| 扎赉特旗| 同江市| 美姑县| 穆棱市| 修武县| 普兰县| 宜兰市| 临泽县| 南江县| 鲁甸县| 万宁市| 辰溪县| 闽侯县| 岳普湖县| 同心县| 措美县| 泉州市| 东安县| 手游| 信宜市| 西充县| 黑山县| 乐平市| 香港 | 永州市| 双城市| 前郭尔| 海兴县| 渝北区| 县级市| 高邑县| 潮安县| 道真| 忻州市| 长寿区| 阿坝县|