場景
Android中,“搜索”事件無非下面兩種場景:
1、從網(wǎng)絡(luò)中搜索資源
2、從本地(緩存、內(nèi)存)中搜索資源
下面是個(gè)搜索的gif,要做到最優(yōu)體驗(yàn),首先應(yīng)該盡量避免無用的計(jì)算工作以及占用無意義的資源。

最優(yōu)解
1、從網(wǎng)絡(luò)中搜索資源
因?yàn)榫W(wǎng)絡(luò)資源需要流量的開銷,并且網(wǎng)絡(luò)請求過程不容易控制,所以該解決方案主要從流量、性能方便考慮。
設(shè)置一個(gè)延遲時(shí)間,過濾掉變化過快的字符:
比如設(shè)置延時(shí)時(shí)間為200ms,當(dāng)用戶輸入'a'后,200ms內(nèi)沒輸入新的字符,則200ms后,根據(jù)‘a(chǎn)’來搜索首字母為'a'的數(shù)據(jù)源;
如果用戶輸入'a'后,緊接著很快輸入了'b','c'(每個(gè)字符間隔時(shí)間小于200ms),則在'c'輸入200ms后,根據(jù)'abc'來搜索首字母為'abc'的數(shù)據(jù)源。
總結(jié):該方案非常適合搜索網(wǎng)絡(luò)資源時(shí)使用。這種方案有效減少不必要的流量開銷,提升了用戶體驗(yàn)。
安利:如果你使用了RxJava,一個(gè)操作符就可以幫你搞定:Debounce。Debounce操作符會(huì)過濾掉發(fā)射速率過快的數(shù)據(jù)項(xiàng)。這里有一篇簡友翻譯的使用RxJava提升用戶體驗(yàn)的簡書。
2、從本地(緩存、內(nèi)存)中搜索資源
因?yàn)閺谋镜刂兴阉髻Y源相比較網(wǎng)絡(luò)中速度較快,整個(gè)搜索過程完全可控,所以該解決方案主要從搜索速度上考慮。
單個(gè)子線程處理搜索,配合標(biāo)志位,及時(shí)停止無意義的搜索過程:
比如當(dāng)用戶輸入'a',會(huì)立刻進(jìn)行查找,如果直到查找到結(jié)果也沒有新的字符變化時(shí),則顯示結(jié)果;如果在查找過程中,用戶緊接著輸入'b',則立即停止'a'的搜索過程,重新以'ab'字符開始搜索首字母為'ab'的數(shù)據(jù)源。
總結(jié):該方案非常適合搜索本地資源時(shí)使用。這種方案查找搜索結(jié)果是最高效的。
談?wù)剬?shí)現(xiàn)
上述兩種解決方案都可以使用HandlerThread + 標(biāo)志位的方式實(shí)現(xiàn)。
HanlderThread本質(zhì)就是Thread + Looper,想深入了解HandlerThread的,可以查看Hongyang大神的這篇博客
另外有一種更科學(xué)的方式:SingleThreadExecutor線程池;相比HandlerThread,線程池配合Future可以用更簡潔的代碼實(shí)現(xiàn)我們的需求。
下面以這種場景為例:
// 創(chuàng)建 SingleThreadExecutor
mExecutorService = Executors.newSingleThreadExecutor();
// 每當(dāng)數(shù)據(jù)變化時(shí)調(diào)用
void onDataChanged() {
if (mFuture != null) {
// 數(shù)據(jù)變化時(shí),取消上一個(gè)任務(wù)
mFuture.cancel(true);
}
// 執(zhí)行異步任務(wù)
mFuture = mExecutorService.submit(new Runnable() {
@Override
public void run() {
final ArrayList<Result> resultDatas = filterDatas(datas);
post(new Runnable() {
@Override
public void run() {
// 根據(jù)resultDatas 更新UI
}
});
}
});
}
上面代碼就是整個(gè)實(shí)現(xiàn)過程了,注釋應(yīng)該解釋的很清楚啦,就不多廢話了。
至于第一種方案的實(shí)現(xiàn),如果不用RxJava的話,使用HandlerThread也是可以實(shí)現(xiàn)的,不需要標(biāo)志位(網(wǎng)絡(luò)請求一般是不可控的,標(biāo)志位沒什么意義),而是配合Hanlderd的removeCallbacks方法,或者removeMessages方法移除Callback/Messages。具體實(shí)現(xiàn)感興趣的,可以自己去試試吧。