等到用户停止输入后再在搜索视图中执行大量搜索
Wait until the user stops typing before executing a heavy search in searchview
搜索是我应用程序的核心,我需要它才能正常运行。现在我有一个 SearchView。我需要内联显示结果,所以我使用了这段代码。
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
srl.setVisibility(View.GONE);
return false;
}
@Override
public boolean onQueryTextChange(String query) {
currentQuery = query;
if (query.length()>= 3) {
searchFor(currentQuery);
} else {
srl.setVisibility(View.GONE);
}
return false;
}
});
问题可能很明显。因为我使用 firebase,所以我的 searchFor()
函数相当繁重,我不需要为每个字母都执行它。这不仅会破坏用户体验,如果您写下更长的单词,有时还会使我的应用崩溃。
我想要的是在用户停止输入时进行搜索。我想我需要有一个处理程序将它延迟一秒钟,然后在每次按下字母键并设置一个新键时取消该处理程序。这在理论上是有道理的。我只是无法通过 searchView 自行解决这个问题。
不胜感激!
最简单的方法是 RxJava's debounce 运算符。
结合 Jake Wharton 的 RxBinding 你会得到这样的结果:
RxSearchView.queryTextChanges(searchView)
.debounce(1, TimeUnit.SECONDS) // stream will go down after 1 second inactivity of user
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<CharSequence>() {
@Override
public void accept(@NonNull CharSequence charSequence) throws Exception {
// perform necessary operation with `charSequence`
}
});
这应该对您有所帮助,您的 class 需要实施 "SearchView.OnQueryTextListener" 并且 "cntr" 必须在您的 class
中声明
这已经为普通用户输入提供了 twinked,如果您想等待更多,只需提高 "waitingTime"。
请求应该在 "onFinish"
内
private int waitingTime = 200;
private CountDownTimer cntr;
@Override
public boolean onQueryTextChange(String newText) {
if(cntr != null){
cntr.cancel();
}
cntr = new CountDownTimer(waitingTime, 500) {
public void onTick(long millisUntilFinished) {
Log.d("TIME","seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
Log.d("FINISHED","DONE");
}
};
cntr.start();
return false;
}
参考:
对于那些不想使用 RxJava 的人:
final Handler handler = new Handler();
SearchView searchView = (SearchView) findViewById(R.id.search_view);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
public boolean onQueryTextChange(final String query) {
handler.removeCallbacksAndMessages(null);
handler.postDelayed(new Runnable() {
@Override
public void run() {
// do stuff
}
}, 400);
return false;
}
});
搜索是我应用程序的核心,我需要它才能正常运行。现在我有一个 SearchView。我需要内联显示结果,所以我使用了这段代码。
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
srl.setVisibility(View.GONE);
return false;
}
@Override
public boolean onQueryTextChange(String query) {
currentQuery = query;
if (query.length()>= 3) {
searchFor(currentQuery);
} else {
srl.setVisibility(View.GONE);
}
return false;
}
});
问题可能很明显。因为我使用 firebase,所以我的 searchFor()
函数相当繁重,我不需要为每个字母都执行它。这不仅会破坏用户体验,如果您写下更长的单词,有时还会使我的应用崩溃。
我想要的是在用户停止输入时进行搜索。我想我需要有一个处理程序将它延迟一秒钟,然后在每次按下字母键并设置一个新键时取消该处理程序。这在理论上是有道理的。我只是无法通过 searchView 自行解决这个问题。
不胜感激!
最简单的方法是 RxJava's debounce 运算符。
结合 Jake Wharton 的 RxBinding 你会得到这样的结果:
RxSearchView.queryTextChanges(searchView)
.debounce(1, TimeUnit.SECONDS) // stream will go down after 1 second inactivity of user
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<CharSequence>() {
@Override
public void accept(@NonNull CharSequence charSequence) throws Exception {
// perform necessary operation with `charSequence`
}
});
这应该对您有所帮助,您的 class 需要实施 "SearchView.OnQueryTextListener" 并且 "cntr" 必须在您的 class
中声明这已经为普通用户输入提供了 twinked,如果您想等待更多,只需提高 "waitingTime"。
请求应该在 "onFinish"
内 private int waitingTime = 200;
private CountDownTimer cntr;
@Override
public boolean onQueryTextChange(String newText) {
if(cntr != null){
cntr.cancel();
}
cntr = new CountDownTimer(waitingTime, 500) {
public void onTick(long millisUntilFinished) {
Log.d("TIME","seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
Log.d("FINISHED","DONE");
}
};
cntr.start();
return false;
}
参考:
对于那些不想使用 RxJava 的人:
final Handler handler = new Handler();
SearchView searchView = (SearchView) findViewById(R.id.search_view);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
public boolean onQueryTextChange(final String query) {
handler.removeCallbacksAndMessages(null);
handler.postDelayed(new Runnable() {
@Override
public void run() {
// do stuff
}
}, 400);
return false;
}
});