關(guān)于延遲搜索的幾種實現(xiàn)方式

場景

在進(jìn)行搜索功能開發(fā)(特別是需要從網(wǎng)絡(luò)或者本地加載)的時候幔崖,為了給用戶以更好體驗:

比如用戶想要搜索“abc”,如果每次輸入的文字變化都執(zhí)行一次請求(確實很垃圾)坑雅,那么就會陸續(xù)搜索“a”,“ab”,“abc”。這還是在搜索比較少的情況下,如果搜索字?jǐn)?shù)較多,又或者網(wǎng)絡(luò)狀況不好学赛,那么用戶的體驗一定會很差,所以節(jié)流就很有必要性吞杭。通常的做法便是:

設(shè)置一個延遲時間盏浇,過濾掉變化過快的字符

而實現(xiàn)的方式,我總結(jié)了有以下三種:

  • Handler+Thread
  • Executor+Future
  • RxJava
screenshot.gif
screenshot.gif

apk地址:Demo

實現(xiàn)(延遲500ms搜索)

1.Handler+Thread

第一種方式使用我們都很熟悉的Handler,配合Hanlder的removeCallbacks方法芽狗,或者removeMessages方法移除Callback/Messages缠捌。延遲的話使用postDelayed方法就可以實現(xiàn)。

    @Override
    public boolean onQueryTextChange(String newText) {
        if (!TextUtils.isEmpty(newText)) {
            queryWithHandler(newText);
        }
        return true;
    }

    private void queryWithHandler(String newText) {
        // 延遲
        if (delayQueryTask != null) {
            delayQueryTask.cancel();
            handler.removeCallbacksAndMessages(null);
        }
        delayQueryTask = new DelayQueryRunnable(newText);
        handler.postDelayed(delayQueryTask, 500);
    }

    private class DelayQueryRunnable implements Runnable {
        String mText;
        private boolean canceled = false;

        public DelayQueryRunnable(String text) {
            this.mText = text;
        }

        @Override
        public void run() {
            if (canceled) {
                return;
            }
            queryMatch(mText);
        }

        public void cancel() {
            canceled = true;
        }
    }

2.Executor+Future

Future模式可以這樣來描述:我有一個任務(wù),提交給了Future曼月,F(xiàn)uture替我完成這個任務(wù)谊却。期間我自己可以去做任何想做的事情。一段時間之后哑芹,我就便可以從Future那兒取出結(jié)果

在onQueryTextChange函數(shù)即輸入框內(nèi)容每次變化時將一個數(shù)據(jù)獲取線程SearchThread放到scheduledExecutor中炎辨,如果當(dāng)前正在執(zhí)行搜索,那么取消這個任務(wù)重新搜索聪姿,避免不必要的數(shù)據(jù)獲取和多個搜索提示同時出現(xiàn)碴萧。

    @Override
    public boolean onQueryTextChange(String newText) {
        if (!TextUtils.isEmpty(newText)) {
            showSearchTip(newText);
        }
        return true;
    }

    private MyHandler mHandler ;
    private Future<?> mFuture;
    // 創(chuàng)建 SingleThreadExecutor
    ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();

    public ScheduledFuture<?> schedule(Runnable command, long delayTimeMills) {
        return scheduledExecutor.schedule(command, delayTimeMills, TimeUnit.MILLISECONDS);
    }

    public void showSearchTip(String newText) {
        if (mFuture!=null){
            //取消任務(wù),true代表立即取消
            mFuture.cancel(true);
        }
        // 延遲500毫秒
        mFuture=schedule(new SearchThread(newText), 500);
    }

    class SearchThread implements Runnable {

        String newText;

        public SearchThread(String newText) {
            this.newText = newText;
        }

        public void run() {
            if (!TextUtils.isEmpty(newText)) {
                mHandler.sendMessage(mHandler.obtainMessage(1, newText ));
            }
        }
    }

    private class MyHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    queryMatch((String) msg.obj);
                    break;
            }
        }
    }

3.RxJava

使用rxjava最簡單末购,使用PublishSubjectDebounce操作符很容易實現(xiàn)延遲搜索破喻。PublishSubject既是發(fā)送者也是接收者,可以用于接收變化的字符串盟榴,而Debounce操作符會過濾掉發(fā)射速率過快的數(shù)據(jù)項曹质,更多優(yōu)化可以看這一篇使用RxJava 提升用戶體驗

    private PublishSubject<String > mSubject=PublishSubject.create();

    private void initData() {
       //其他操作
      
        mSubject.debounce(500, TimeUnit.MILLISECONDS)//延遲500ms
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        //從網(wǎng)絡(luò)或者本地搜索
                        queryMatch(s);
                    }
                }).subscribe();    
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        if (!TextUtils.isEmpty(newText)) {
            queryWithRxJava(newText);
        }
        return true;
    }

    private void queryWithRxJava(String newText) {
        //發(fā)送數(shù)據(jù)源
        mSubject.onNext(newText);
    }

結(jié)語

三種方法介紹完畢擎场,也許可以做些優(yōu)化羽德,使用HandlerThread什么的,或者還有其他更好的方法迅办,歡迎交流宅静。

附上git地址 : https://github.com/ditclear/RealTimeSearch

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市站欺,隨后出現(xiàn)的幾起案子姨夹,更是在濱河造成了極大的恐慌,老刑警劉巖矾策,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匀伏,死亡現(xiàn)場離奇詭異,居然都是意外死亡蝴韭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門熙侍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來榄鉴,“玉大人,你說我怎么就攤上這事蛉抓∏斐荆” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵巷送,是天一觀的道長驶忌。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么付魔? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任聊品,我火速辦了婚禮,結(jié)果婚禮上几苍,老公的妹妹穿的比我還像新娘翻屈。我一直安慰自己,他們只是感情好妻坝,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布伸眶。 她就那樣靜靜地躺著,像睡著了一般刽宪。 火紅的嫁衣襯著肌膚如雪厘贼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天圣拄,我揣著相機與錄音嘴秸,去河邊找鬼。 笑死售担,一個胖子當(dāng)著我的面吹牛赁遗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播族铆,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼岩四,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哥攘?” 一聲冷哼從身側(cè)響起剖煌,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逝淹,沒想到半個月后耕姊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡栅葡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年茉兰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片欣簇。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡规脸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出熊咽,到底是詐尸還是另有隱情莫鸭,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布横殴,位于F島的核電站被因,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梨与,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一堕花、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蛋欣,春花似錦航徙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至尚猿,卻和暖如春窝稿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凿掂。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工伴榔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人庄萎。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓踪少,卻偏偏與公主長得像,于是被迫代替她去往敵國和親糠涛。 傳聞我的和親對象是個殘疾皇子援奢,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容