Delay call to onQueryTextChange() in SearchView.OnQueryTextListener with SearchView
Asked Answered
W

5

20

Using a SearchView in my application.

Is there anyway in which I can make the call to onQueryTextChange() method delayed. Like, when user type a sequence of characters, he must wait before this method gets called.

This wait should not depend on number of characters typed yet but a small pause is required before method being hit.

I want to pause because, as the user types into the search view, a request with the string will be made to server to request the matched data, and then I will populate my ListView according to suggestions.

Activity information (if required) :
Implements SearchView.OnQueryTextListener.

    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView)MenuItemCompat.getActionView(searchItem);
    searchView.setOnQueryTextListener(this);
Whited answered 5/5, 2015 at 8:19 Comment(8)
no, why do you need that?Whet
You can use a TimerTask to delay filtering your list. Put the code of filtering inside the timer. However I would not recommend delaying search.Grivation
@Whet To fetch data from server as the user types into the SearchView. Request must not be made every time a character is typed, rather, there should be a pause.Whited
@Skynet Please elaborate, why don't you recommend a TimerTask?Whited
use a Filterable interface, please don't reinvent the wheel, you can use FilterQueryProvider for exampleWhet
I second using a FilterQueryProvider. I said I dont recommend delaying search, you can use a timer task. If you dont want to access the server each time, allow the user to use the submit button of the SearchView.Grivation
@Skynet Why not to delay search? User usually knows what they are searching for (at least in my case, they do). If the search isn't delayed, ListView will get populated with 'S' suggestions, followed by "Sk", "Sky", till "Skynet". Though I know that the past data from ListView can be flushed.Whited
Seen how Play Store does it - super fast?Grivation
A
40

To delay the call to your server, use the following code in your onQueryTextChange method, the variables mQueryString and mHandler must be class variables. also check mHandler!=null

@Override
public boolean onQueryTextChange(String searchTerm) {
    mQueryString = searchTerm;
    mHandler.removeCallbacksAndMessages(null);

    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
           //Put your call to the server here (with mQueryString)
        }
    }, 300);
    return true;
}
Ap answered 30/10, 2015 at 11:17 Comment(1)
Thanks that was grate.Hybris
S
10

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;
}
Snowfield answered 21/7, 2017 at 16:16 Comment(1)
This should be the accepted answer because the first answer has the undesirable effect to call the method 'run' twiceFtlb
C
7

You can use Kotlin coroutines like this. Declare the countdown job

private lateinit var textChangeCountDownJob: Job

And then onQueryTextChange:

    override fun onQueryTextChange(newText: String): Boolean {

        if(::textChangeCountDownJob.isInitialized)
            textChangeCountDownJob.cancel()

        textChangeCountDownJob = launch(UI) {
            delay(800)
        }

        return false
    }
Camden answered 31/5, 2018 at 7:7 Comment(2)
i think using coroutines is simple and more effective. but which package does the launch method is from?Jolo
@Jolo textChangeCountDownJob = lifecycleScope.launch { .. }Flannery
S
2

Delay call to onQueryTextChange() in SearchView.OnQueryTextListener with SearchView

private long delay = 2000; 
private long editTextLastWord = 0;
privaste  SearchView searchView;
Handler handler = new Handler();

private Runnable runnable = new Runnable() {
    public void run() {
        if (System.currentTimeMillis() > (editTextLastWord + delay - 500)) {

          perFormTask();
        }
    }
};
 searchView=(SearchView) findViewById(R.id.searchView);
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
 if (s.length() > 2) {              
          editTextLastWord = System.currentTimeMillis();
          handler.postDelayed(runnable, delay);
        } else {

        }
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                return false;
  handler.removeCallbacks(runnable);
            }
        });
Smtih answered 19/7, 2017 at 10:41 Comment(0)
I
2

1) Create abstract class:

public abstract class DelayedOnQueryTextListener implements SearchView.OnQueryTextListener {

    private Handler handler = new Handler();
    private Runnable runnable;

    @Override
    public boolean onQueryTextSubmit(String s) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String s) {
        handler.removeCallbacks(runnable);
        runnable = () -> onDelayerQueryTextChange(s);
        handler.postDelayed(runnable, 400);
        return true;
    }

    public abstract void onDelayerQueryTextChange(String query);
}

2) Set it like this:

searchView.setOnQueryTextListener(new DelayedOnQueryTextListener() {
    @Override
    public void onDelayerQueryTextChange(String query) {
        // Handle query
    }
});
Inhumation answered 20/3, 2019 at 9:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.