AutoCompleteTextView, не отображающий результат, даже когда ArrayAdapter обновляется

Я пытаюсь заставить AutoCompleteTextView (ACTV) отображать результаты, я - получение от сетевого ресурса. Я установил завершение-treshold на 2, и я вижу, что запрос запущен, когда я вхожу в символы.

Результатом, который я получаю, является корректный. Позволяет говорят, что я пишу "приблизительно", и я получаю результат "автомобиль" как автозавершение. У меня есть функция обратного вызова, которая получает результат AsyncTask и помещает результат в ArrayAdapter. Затем я называю .showDropDown () на ACTV, и пустое выпадающее показывают (половина размера нормального элемента). Затем, если я ввожу последнюю букву "r", и ACTV показывает "автомобиль", выпадающее показывают, и результат внезапно находится в списке.

То же происходит, если я ввел два символа (который возвращает допустимый результат), и удаление последней буквы. Когда буква удалена, "автомобиль" показывается значением автозавершения.

У кого-либо была эта проблема? Похоже, что адаптер заполнен результатом, но результат не показывает до следующего действия я делаю. Я также попытался выполнить .notifyDataSetChanged () после того, как я добавил результат к адаптеру, но это не должно быть необходимо, или?

7
задан Eric Nordvik 19 April 2010 в 22:41
поделиться

1 ответ

Не видя вашего кода, трудно сказать, что может происходить. Но первое, что приходит в голову, это то, что ваш сетевой запрос выполняется в другом потоке, и поэтому ваш performFiltering () может преждевременно возвращать пустой набор результатов. В этот момент publishResults () возвращает пустой результат, а раскрывающийся список пуст. Позже ваша AsyncTask вернет свой результат, и вы добавите результаты в список адаптера, но по той или иной причине он еще не отображается.

Я думаю, вы ошибаетесь насчет необходимости AsyncTask. Объект Filter уже выполняет что-то похожее на AsyncTask: performFiltering () выполняется в фоновом потоке, а publishResults () вызывается из потока пользовательского интерфейса после завершения performFiltering () . Таким образом, вы можете выполнить свой сетевой запрос непосредственно в performFiltering () и установить результаты в объект FilterResults, и вам не придется беспокоиться о том, что сетевой запрос будет слишком медленным и вызовет проблемы в вашем пользовательском интерфейсе.

Альтернативное решение, которое немного сложнее, но это то, что я делаю в своем объекте Filter (из-за существующей архитектуры, которая выполняет вызовы API в фоновом режиме, используя асинхронный обратный вызов вместо блокирующего / синхронного шага по мере необходимости. для performFiltering ()) заключается в использовании синхронизированного объекта с wait () / notify () для выполнения межпоточного мониторинга, поэтому эффект такой же, как при выполнении сетевого запроса непосредственно в performFiltering (), но на самом деле это происходит в нескольких thread:

// in Filter class..
protected FilterResults performFiltering(CharSequence constraint) {

    APIResult response = synchronizer.waitForAPI(constraint);
    // ...
}

// callback invoked after the API call finishes:
public void onAPIComplete(APIResult results) {
    synchronizer.notifyAPIDone(results);
}

private class Synchronizer {
    APIResult result;

    synchronized APIResult waitForAPI(CharSequence constraint) {
        someAPIObject.startAsyncNetworkRequest(constraint);
        // At this point, control returns here, and the network request is in-progress in a different thread.
        try {
            // wait() is a Java IPC technique that will block execution until another
            // thread calls the same object's notify() method.
            wait();
            // When we get here, we know that someone else has just called notify()
            // on this object, and therefore this.result should be set.
        } catch(InterruptedException e) { }
        return this.result;
    }

    synchronized void notifyAPIDone(APIResult result) {
        this.result = result;
        // API result is received on a different thread, via the API callback.
        // notify() will wake up the other calling thread, allowing it to continue
        // execution in the performFiltering() method, as usual.
        notify();
    }
}

Однако я думаю, что вы можете обнаружить, что самое простое решение - это просто синхронно выполнять сетевой запрос непосредственно в методе performFiltering (). Приведенный выше пример кода является лишь одной из возможностей, если у вас уже есть архитектура для асинхронных / управляемых обратным вызовом API-вызовов, и вы не хотите изменять это поведение, чтобы получить синхронные результаты в performFiltering ().

16
ответ дан 6 December 2019 в 11:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: