应用场景
在平时开发过程中,关键字搜索的场景还是挺多的,为了避免频繁请求,必须要对请求触发做一定限制,对用户体验进行优化。
这里通过Rxjava中debounce操作符,做一个限流实现。
代码实现
这里使用的是Rxjava2.0,首先,请先添加依赖
dependencies {
compile 'io.reactivex.rxjava2:rxjava:2.1.3'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
}
设置搜索框输入的监听:
private TextWatcher mGlobalSearchWatcher = 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) {
String globalSearchKey = s.toString();
Log.d(TAG, "global search key =" + globalSearchKey);
if (TextUtils.isEmpty(globalSearchKey)) {
mSearchManager.cancelSearch(); // 取消搜索
mSearchResultAdapter.clearResult();
} else {
mSearchManager.launchSearch(globalSearchKey);// 发起搜索
}
}
};
mGlobalSearchKey.addTextChangedListener(mGlobalSearchWatcher);
实例化一个PublishSubject对象,通过debounce操作符进行限流设置,并订阅回调:
private PublishSubject<String> mSubject;
private void initPublishSubject() {
mSubject = PublishSubject.create();
mSubject.debounce(300, TimeUnit.MILLISECONDS) // 这里设置了300ms的限制
.observeOn(SchedulerProvider.getInstance().ui())
.subscribe(new Consumer<String>() {
@Override
public void accept(String keyword) throws Exception {// 这里会收到被限流后onNext发出的事件,过滤掉未到300ms发出的事件
if ("cancel_request".equals(keyword)) { // 这里做了一个特殊处理,当关键字为空时,不进行搜索
LogUtils.i(TAG, "search: cancel request");
return;
}
doSearchRecommendedApp(keyword);
}
});
}
发送关键字,每一个关键字就是一个事件:
private void searchRecommendedApp(String keywords) {
Log.i(TAG, "search: enter searchRecommendedApp, keywords = " + keywords);
boolean available = Utils.isNetworkAvailable(mLauncher.getApplicationContext());
if (!available) {
//LogUtils.d(TAG, "search: searchRecommendedApp, network is not available");
return;
}
mSubject.onNext(keywords); // 当关键字变化时,发送关键字
}
关键为空时,发送一个特殊的关键字:
public void cancelSearch() {
// cancel request if request not sended out
Log.i(TAG, "search: enter cancelSearch");
mSubject.onNext("cancel_request"); // 当关键字为空时,发送特殊关键字
}