Napisałem ListActivity z niestandardową listą adapterów. Lista jest aktualizowana z ContentProvider po uruchomieniu onCreate. Mam też usługę, która uruchamia się po uruchomieniu aplikacji i najpierw aktualizuje ContentProvider, a następnie wysyła audycję, w której zawartość została zaktualizowana.
Moja ListActivity odbiera transmisję i próbuje zaktualizować mój ListView. Mój problem polega na tym, że dostaję sporadyczne błędy dotyczące zmiany danych adaptera ListView bez powiadomienia ListView. Wywołuję metodę notifyDataSetChanged()
na moim adapterze list zaraz po aktualizacji. Wygląda na to, że lista jest wciąż aktualizowana po pierwszym wywołaniu onCreate, gdy odbiera transmisję z usługi do aktualizacji, więc próbuje zaktualizować mój ListView, zanim zakończy aktualizację od pierwszego uruchomienia. Czy to ma sens? Oto niektóre z mojego kodu.Zmiana danych adaptera ListView bez powiadomienia o liście ListView
UWAGA: Usługa działa poprawnie, pobiera nowe dane i aktualizuje mojego dostawcę treści, a transmisję otrzymuję w mojej aktywności po jej zaktualizowaniu.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
getPrefs();
setContentView(R.layout.main);
// Setup preference listener
preferences = PreferenceManager.getDefaultSharedPreferences(this);
preferences.registerOnSharedPreferenceChangeListener(listener);
// Setup report list adapter
ListView nzbLv = (ListView) findViewById(R.id.report_list);
nzbla = new NZBReportListAdaptor(ctx);
getReports();
nzbla.setListItems(report_list);
nzbLv.setAdapter(nzbla);
// Broadcast receiver to get notification from NZBService to update ReportList
registerReceiver(receiver,
new IntentFilter(NZBService.BROADCAST_ACTION));
startService(new Intent(ctx, NZBService.class));
}
@Override
public void onResume() {
super.onResume();
timerHandler.resume();
new updateSabQueue().execute();
//updateList();
}
@Override
public void onPause() {
super.onPause();
timerHandler.pause();
unregisterReceiver(receiver);
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
Toast.makeText(ctx, "NZBService broadcast recieved", Toast.LENGTH_SHORT).show();
updateReportList();
}
};
private void updateReportList() {
new updateReportList().execute();
}
private class updateReportList extends AsyncTask<Void, Void, Boolean> {
/* (non-Javadoc)
* @see android.os.AsyncTask#onPreExecute()
* Show progress dialog
*/
protected void onPreExecute() {
}
/* (non-Javadoc)
* @see android.os.AsyncTask#doInBackground(Params[])
* Get new articles from the internet
*/
protected Boolean doInBackground(Void...unused) {
getReports();
return true;
}
/**
* On post execute.
* Close the progress dialog
*/
@Override
protected void onPostExecute(Boolean updated) {
if (updated) {
Log.d(TAG, "NZB report list adapter updated");
synchronized(this) {
nzbla.setListItems(report_list);
}
Log.d(TAG, "NZB report list notified of change");
nzbla.notifyDataSetChanged();
}
}
}
Teraz, to odpowiedź na pytanie, będę pisać mój zaktualizowany kod, starając się pomóc innym, którzy mogą wejść w poprzek.
To jest dokładnie problem. Mój adapter list jest wspierany przez ArrayList obiektów "report_list" i modyfikuję go bezpośrednio w mojej metodzie getReports, która jest wykonywana w osobnym wątku.Zmodyfikowałem metodę getReports, aby działała na lokalnej tablicy ArrayList i zwróciłem ją (i przekazałem dalej do mojej metody onPostExecute). Chociaż zdawałem sobie sprawę z faktu, że nie mogę operować na moich danych adaptera listy poza wątkiem interfejsu użytkownika, po prostu nie chwytałem go w 100%, dopóki nie zawiódł mnie i zmusił mnie do znalezienia go poprawnie (lub dokładniej zapytałem o pomoc tutaj!) Dziękuję Qberticus! – brockoli