web-dev-qa-db-fra.com

Android SimpleCursorAdapter ne se met pas à jour lorsque la base de données change

J'ai une Android ListActivity qui est sauvegardée par une base de données Cursor à travers une SimpleCursorAdapter.

Lorsque les éléments sont cliqués, un champ d'indicateur dans la ligne correspondante de la base de données est basculé et la vue dans la liste doit être mise à jour. 

Le problème est que, lorsque la vue mise à jour disparaît de l'écran et est recyclée, l'ancienne valeur est affichée dans la vue lorsqu'elle redevient visible. La même chose se produit chaque fois que la liste est redessinée (changements d’orientation, etc.). 

J'utilise notifydatasetchanged() pour actualiser l'adaptateur de curseur mais cela semble inefficace.

Comment devrais-je mettre à jour la base de données pour que le curseur soit également mis à jour?

43
CodeFusionMobile

Appelez requery() sur la Cursor lorsque vous modifiez dans la base de données les données que vous souhaitez refléter dans cette Cursor (ou les éléments remplis par la Cursor, comme une ListView via une CursorAdapter).

Une Cursor s'apparente à un curseur côté client ODBC - elle contient toutes les données représentées par le résultat de la requête. Par conséquent, juste parce que vous modifiez les données dans la base de données, la Cursor ne saura rien de ces modifications que si vous l'actualisez via requery().


UPDATE: Toute cette question et cet ensemble de réponses devraient être supprimés en raison de la vieillesse, mais c'est apparemment impossible. Toute personne à la recherche de réponses sur Android devrait garder à l’esprit le fait qu’Android est une cible qui se déplace rapidement, et que les réponses de 2009 sont généralement pires que les nouvelles réponses.

La solution actuelle consiste à obtenir une nouvelle Cursor et à utiliser soit changeCursor(), soit swapCursor() sur CursorAdapter pour modifier les données.

90
CommonsWare

requery est maintenant obsolète. de la documentation :

Cette méthode est obsolète . Ne l'utilisez pas. Demandez simplement un nouveau curseur afin de pouvoir le faire de manière asynchrone et mettre à jour la vue de liste une fois que le nouveau curseur sera revenu.

après avoir obtenu un nouveau curseur, vous pouvez utiliser la adapter.changeCursor(cursor). cela devrait mettre à jour la vue.

37
rony l

En cas d'utilisation du chargeur et du curseur généré automatiquement, vous pouvez appeler:

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

dans votre activité, juste après avoir modifié quelque chose sur une base de données, pour régénérer un nouveau curseur . N'oubliez pas de définir également les gestionnaires d'événements:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    CursorLoader cursorLoader =
            new CursorLoader(this,
                    YOUR_URI,
                    YOUR_PROJECTION, null, null, null);
    return cursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    adapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    adapter.swapCursor(null);
}
21
siefca

Je ne sais pas si vous définissez la propriété autoRequery de CursorAdapter sur true.

L'adaptateur vérifiera la propriété autoRequery; si c'est false, alors le curseur ne sera pas changé.

1
gjican

C'est 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);

Ou utilisez CursorLoader ...

0
Shwarz Andrei

requery () est déjà obsolète, implémentez simplement la méthode updateUI () comme celle-ci dans la classe enfant de votre CursorAdapter et appelez-la après la mise à jour des données:

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