Лаг EditText при поиске списка в textWatcher - PullRequest
0 голосов
/ 19 мая 2018

Вот мой TextWatcher:

searchBox.addTextChangedListener(new TextWatcher() {

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

            }

            @Override
            public void onTextChanged(final CharSequence charSequence, int i, int i1, int i2) {
                ArrayList<ProductInformation> newList = new ArrayList<>();
                for (ProductInformation info : currentList)
                    if (info.getName().contains(charSequence))
                        newList.add(info);
                productListAdapter.setNewData(newList);

            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });

После добавления этого listener к моему editText его отставание при наборе текста.Я предполагаю, что проблема заключается в поиске в списке (список содержит от 40 до 60 элементов).

Что я могу сделать?

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

Текстовый поиск в режиме реального времени предъявляет некоторые требования для повышения производительности:

Требование

  • Не следует начинать поиск сразу, потому чтоСкорость набора текста пользователем достаточно высока, и следующий результат немедленно переопределяет последний.Несколько процессов поиска выполняются, но будет показан только последний результат, который будет потрачен впустую.

  • Попробуйте сделать поиск асинхронным, даже если это сетевой запрос или просто локальный поиск, чтобы он выигралНе вредит пользовательскому интерфейсу и может быть легко отменен.

Решение

Используйте Timer и TimerTask для задержки и отмены во время ввода

private Timer mRequestDelayTimer;
private TimerTask mSearchTask;

@Override
public void onTextChanged(final CharSequence query, int i, int i1, int i2) {
    if (mRequestDelayTimer != null)
        mRequestDelayTimer.cancel();

    // If you do a async search, stop it here
    stopSearch();

    mRequestDelayTimer = new Timer();
    mSearchTask = new TimerTask() {
        @Override
        public void run() {
            startSearch(query);
        }
    };
    mRequestDelayTimer.schedule(mSearchTask, 500);
}

private synchronized void startSearch(String query) {
    // This is not run in UI thread. Use activity.runOnUiThread if you want to update the UI
    // Call an AsyncTask to do an async search or run a sync loop search here

    //ArrayList<ProductInformation> newList = new ArrayList<>();
    //for (ProductInformation info : currentList)
    //    if (info.getName().contains(charSequence))
    //        newList.add(info);
    //productListAdapter.setNewData(newList);
}

Объяснение

Если каждый введенный символ находится в пределах 500 мс, он не вызывает startSearch, поскольку таймер продолжает задерживаться.

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

Если вы выполняете поиск и обновляете результат в ArrayAdapter, он имеет встроенный процесс Filter.в, вы можете настроить его, переопределив getFilter.Этот фильтр автоматически запускается в фоновом режиме, делает отмену для каждого ввода символов, очень удобно.Ссылка: Пользовательский getFilter в пользовательском ArrayAdapter в Android

Реальная реализация может отличаться, но идея та же

0 голосов
/ 19 мая 2018

Вы можете избежать отставания времени поиска с логикой, что если разница во времени между двумя введенными символами составляет больше определенного времени, тогда вы начинаете поиск в списке для обновления productListAdapter а если нет, то оставайтесь без дела.

Вот исходный код:

        startTime = System.currentTimeMillis();
        endTime = System.currentTimeMillis();
        searchBox.addTextChangedListener(new TextWatcher() {

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

        }

        @Override
        public void onTextChanged(final CharSequence charSequence, int i, int i1, int i2) {
            endTime = System.currentTimeMillis();
            if(endTime - startTime >= 1000) {
                ArrayList<ProductInformation> newList = new ArrayList<>();
                for (ProductInformation info : currentList)
                    if (info.getName().contains(charSequence))
                        newList.add(info);
                productListAdapter.setNewData(newList);
            }
            startTime = endTime;
        }

        @Override
        public void afterTextChanged(Editable editable) {

        }
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...