Delay call to onQueryTextChange() in SearchView.On

2020-06-01 07:09发布

问题:

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);

回答1:

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;
}


回答2:

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;
}


回答3:

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
    }


回答4:

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

private long delay = 2000L; 
private long editTextLastWord = 0L;
private  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);
        }
        }

            @Override
            public boolean onQueryTextChange(String newText) {
                return false;
  handler.removeCallbacks(runnable);
            }
        });


回答5:

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
    }
});