Android SimpleCursorAdapter non si aggiorna quando il database cambia

Ho un Android ListActivity supportato da un Cursor database tramite SimpleCursorAdapter .

Quando si fa clic sugli elementi, viene triggersto un campo flag nella riga corrispondente nel database e la visualizzazione nell’elenco deve essere aggiornata.

Il problema è che quando la vista che viene aggiornata si spegne e viene riciclata, il vecchio valore viene visualizzato sulla vista quando ritorna in visualizzazione. La stessa cosa accade ogni volta che la lista è ridisegnata (cambiamenti di orientamento, ecc.).

Io uso notifydatasetchanged() per aggiornare l’adattatore del cursore, ma sembra inefficace.

Come dovrei aggiornare il database in modo che anche il cursore venga aggiornato?

Chiama requery() sul Cursor quando modifichi i dati nel database che desideri vengano visualizzati in quel Cursor (o cose che il Cursor popola, come un ListView tramite un CursorAdapter ).

Un Cursor è simile a un cursore lato client ODBC: contiene tutti i dati rappresentati dal risultato della query. Quindi, solo perché si modificano i dati nel database, il Cursor non conoscerà tali modifiche a meno che non si requery() tramite requery() .


AGGIORNAMENTO : questa intera domanda e insieme di risposte dovrebbero essere cancellate a causa della vecchiaia, ma è apparentemente imansible. Chiunque cerchi risposte per Android dovrebbe tenere a mente che l’Android è un objective in rapida evoluzione e le risposte del 2009 sono in genere peggiori delle risposte più recenti.

La soluzione attuale è ottenere un nuovo Cursor e utilizzare changeCursor() o swapCursor() sul CursorAdapter per influenzare una modifica dei dati.

requery è ora deprecata. dalla documentazione :

Questo metodo è deprecato. Non usare questo. Basta richiedere un nuovo cursore, in modo da poterlo fare in modo asincrono e aggiornare la visualizzazione elenco una volta che il nuovo cursore è tornato.

dopo aver ottenuto un nuovo cursore si può usare l’ adapter.changeCursor(cursor) . questo dovrebbe aggiornare la vista.

In caso di utilizzo del loader e del cursore generato automaticamente, è ansible chiamare:

 getLoaderManager().restartLoader(0, null, this); 

nella tua attività, subito dopo aver modificato qualcosa su un DB, per rigenerare il nuovo cursore. Non dimenticare di definire anche i gestori di eventi:

 @Override public Loader onCreateLoader(int id, Bundle args) { CursorLoader cursorLoader = new CursorLoader(this, YOUR_URI, YOUR_PROJECTION, null, null, null); return cursorLoader; } @Override public void onLoadFinished(Loader loader, Cursor data) { adapter.swapCursor(data); } @Override public void onLoaderReset(Loader loader) { adapter.swapCursor(null); } 

Non sono chiaro se si imposta la proprietà autoRequery di CursorAdapter su true .

L’adattatore controllerà la proprietà autoRequery ; se è false , il cursore non verrà modificato.

requery () è già deprecato, basta implementare il semplice metodo updateUI () come questo nella class figlia del CursorAdapter e chiamarlo dopo gli aggiornamenti dei dati:

 private void updateUI(){ swapCursor(dbHelper.getCursor()); notifyDataSetChanged(); } 

È facile.

 private Db mDbAdapter; private Cursor mCursor; private SimpleCursorAdapter mCursorAd; ..................................... //After removing the item from the DB, use this ..................................... mCursor = mDbAdapter.getAllItems(); mCursorAd.swapCursor(mCursor); 

Oppure usa CursorLoader …