Событие окончания ввода текста в EditText

Пишу приложение для заказа такси, на одной из активити есть EditText и ListVew для поиска адресов из базы, когда пассажир вводит 3 или более символа делаем запрос в базу на совпадение, вопрос такой как можно отловить окончание ввода текста что бы не на каждый ввод текста делать запрос в базу, а например пользователь ввел "мира" идет задержка 2-3 сек если дальше ввода не было делаем запрос в базу.

        searchAdressTextInput.getEditText().addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        };

        @Override
        public void afterTextChanged(Editable s) {
            filterWithDelay(s.toString());
        }
    });

public void filterWithDelay(final String s) {
    latest = (int) System.currentTimeMillis(); //обновляем время последнего изменения текста
    Handler h = new Handler(Looper.getMainLooper());
    Runnable r = new Runnable() {
        @Override
        public void run() {
            if(System.currentTimeMillis() - delay > latest) //если в последние 2 секунды текст не менялся
                Log.d("HELLO", s);
        }
    };
    h.postDelayed(r, delay + 50);//в главный поток с задержкой delay + 50 миллисекунд
}

Ответы (1 шт):

Автор решения: Alex_Skvortsov

На Java при условии отсутствия Rx я бы решал примерно так. Код писался на коленке и без компиляции, возможны синтаксические неточности.

Long latest = 0;
Long delay = 2000; //2 секунды

public void filterWithDelay(String s){ //функция, запускающая запрос в БД через 2 секунды
    latest = System.currentTimeMillis(); //обновляем время последнего изменения текста
    Handler h = new Handler(Looper.getMainLooper());
    Runnable r = new Runnable() {
                @Override
                public void run() {
                    if(System.currentTimeMillis() - delay > latest) //если в последние 2 секунды текст не менялся
                        simpleFilter(s); //сделать запрос в БД
                }
           };
    h.postDelayed(r, delay + 50);//в главный поток с задержкой delay + 50 миллисекунд
}

Update:

Пусть у нас есть в активности / фрагменте переменная EditText c именем editText и она уже инициализирована. Тогда вызов filterWithDelay осуществляем так:

editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {}
    @Override
    public void afterTextChanged(Editable s) {
        filterWithDelay(s.toString())
    }
});

Update 2:

Почему важно объявить переменные именно типом Long?

Дело в том, что тип int ограничен в языке Java значением 4 294 967 296, если попытаться бОльшее число - Вы получите отрицательное число с другим значением. Этот эффект называется переполнение. Тип Long в свою очередь может хранить числа до 100 000 000 000 000 000 000 (примерно). Метод System.currentTimeMillis() возвращает количество миллисекунд, прошедших с определенной даты (если не ошибаюсь, отсчет с 1970 года). Это количество намного больше, чем может вместить int.

→ Ссылка