Reputation: 1090
Search is central in my app and I need it to work well. Right now I have a SearchView. I need to display the results inline, so I'm using this code.
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;
}
});
The problem may be obvious. Because I use firebase, my searchFor()
function is rather heavy and I don't need it to be executed for every single letter. This not only destroys the user experience, it sometimes literally crashes my app if you write down longer words.
What I want is to search when the user stops typing. I guess I need to have a handler that delays it by a second and then cancel that handler everytime a letter key is pressed and set a new one. This theoretically makes sense. I just haven't been able to pull this off myself for a searchView.
Help would be appreciated!
Upvotes: 5
Views: 2916
Reputation: 4603
For those who do not want to use 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;
}
});
Upvotes: 3
Reputation: 644
This should help you, your class need to implement "SearchView.OnQueryTextListener" and "cntr" must be declarated in your class
This is already twinked for a regular user typing, if you want to wait more, just raise the "waitingTime".
The request should be inside the "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;
}
Reference: Delay call to onQueryTextChange() in SearchView.OnQueryTextListener with SearchView
Upvotes: 1
Reputation: 62209
The easiest way to achieve that is RxJava's debounce operator.
With combination of Jake Wharton's RxBinding you'll end up with something like this:
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`
}
});
Upvotes: 5