Подтвердить что ты не робот

Как избежать множественных триггеров в EditText во время ввода пользователем?

Я использую следующий код для выполнения поиска, когда пользователь вводит в EditText:

EditText queryView = (EditText) findViewById(R.id.querybox);
queryView.addTextChangedListener(new TextWatcher() {
  @Override
  public void afterTextChanged(Editable s) {
    triggerSearch(s.toString()); 
  }
  @Override
  public void beforeTextChanged(CharSequence s, int start, int count, int after) {
  }
  @Override
  public void onTextChanged(CharSequence s, int start, int before, int count) {
  }
});

Однако это срабатывает несколько раз, когда пользователь вводит слово. То есть, если пользователь вводит "привет", этот код будет вызывать 5 раз со значениями ( "h", "he", "hel", "hell", "hello" ). Как правило, это было бы хорошо, но поиск был дорогостоящим, и я не хочу тратить ресурсы на промежуточные поиски, которые не имеют большого значения. То, что я хочу, это либо слушатель, который запускает только определенный порог после того, как пользователь начинает вводить текст, либо какой-то фреймворк, который ждет в слушателе перед вызовом triggerSearch, и если другое событие запускается до этого ожидания, отменяет себя.

4b9b3361

Ответ 1

Так как не удалось найти соответствующий интерфейс событий, попробуйте запустить поиск с задержкой. Код на самом деле довольно простой и надежный.

private final int TRIGGER_SERACH = 1;
// Where did 1000 come from? It arbitrary, since I can't find average android typing speed.
private final long SEARCH_TRIGGER_DELAY_IN_MS = 1000;

  private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      if (msg.what == TRIGGER_SERACH) {
        triggerSearch();
      }
    }
  };

 queryView.addTextChangedListener(new TextWatcher() {

   @Override
   public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {

   }

   @Override
   public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {

   }

   @Override
   public void afterTextChanged(Editable s) {
    handler.removeMessages(TRIGGER_SERACH);
    handler.sendEmptyMessageDelayed(TRIGGER_SERACH, SEARCH_TRIGGER_DELAY_IN_MS);
   });

Ответ 2

Одним из решений было бы не выполнять ваш инициированный поиск немедленно, но через некоторый интервал, скажем 100 мс, прошло с момента вызова метода onTextChanged. Дополнительно reset этот интервал при каждом вводе текста.

Таким образом, вызванный поиск не вызывается во время ввода пользователем.

Ответ 3

Ожидание в слушателе перед вызовом triggerSearch; проверьте длину Editable s.

if(s.length() > THRESHOLD)

Ответ 4

Если вы не хотите запускать поиск на каждой нажатой кнопке, вам нужно знать, когда пользователь будет выполнен. Я бы избегал сложных идей по попытке выяснить, когда пользователь набирает текст. Это приведет к тому, что пользователь будет смущен, когда происходит поиск.

Простой ответ затем помещается на кнопку "done" и применяет onClickListener к кнопке и выполняет поиск там.

Самый простой код: в xml

<Button
android:onClick="onDoneClicked"
... the rest of your button layout
/>

в java:

@Override
public void onDoneClicked(View view){
EditText queryView = (EditText) findViewById(R.id.querybox);
triggerSearch(queryView.toString());
}