Nie widząc kodu, trudno powiedzieć, co może się dziać. Ale pierwszą rzeczą, która przychodzi do głowy, jest to, że twoja prośba sieciowa dzieje się w innym wątku, a zatem Twój performFiltering()
może zwracać przedwcześnie pusty zestaw wyników. W tym momencie publishResults()
zwraca pusty wynik, a twoje menu rozwijane jest puste. Później AsyncTask otrzyma wynik z powrotem i doda wyniki do listy adaptera, ale z tego czy innego powodu nie zostanie jeszcze wyświetlony.
Myślę, że możesz się mylić co do potrzeby AsyncTask. Obiekt Filter już robi coś podobnego do AsyncTask: performFiltering()
jest wykonywany w wątku tła, a publishResults()
jest wywoływany z wątku interfejsu użytkownika, po zakończeniu funkcji performFiltering(). Możesz więc wykonać swoje żądanie sieciowe bezpośrednio w performFiltering() i ustawić wyniki w obiekcie FilterResults, a Ty nie będziesz musiał się martwić, że żądanie sieciowe jest zbyt wolne i powoduje problemy w twoim interfejsie.
Alternatywne rozwiązanie, które jest nieco bardziej skomplikowane, ale jest to, co robię w moim obiekcie Filter (ze względu na istniejącą architekturę, która wykonuje wywołania API w tle, za pomocą asynchronicznego wywołania zwrotnego zamiast kroku blokowania/synchronicznego jako wymagane dla funkcji performFiltering()), polega na użyciu zsynchronizowanego obiektu z wait()/notify() w celu wykonania monitorowania krzyżowego, więc efekt jest taki sam, jak wykonanie żądania sieciowego bezpośrednio w performFiltering(), ale tak naprawdę dzieje się to w wiele wątków:
// 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();
}
}
Myślę jednak, że może się okazać, że najprostszym rozwiązaniem jest po prostu zrobić swoje żądanie sieciowe synchronicznie, bezpośrednio w metodzie performFiltering(). Powyższy przykład kodu jest jedną z możliwości, jeśli już posiadasz architekturę dla wywołań funkcji API asynchronicznych/wywoływanych przez wywołania zwrotne i nie chcesz zmieniać tego zachowania, aby uzyskać synchroniczne wyniki w funkcji performFiltering().
Might pomoc, jeśli dodasz swój kod. – Joe