2010-08-23 9 views
16

J'ai une base de données, un ListView, et un CustomCursorAdapter qui s'étend CursorAdapter. Un bouton de menu ajoute un élément à la base de données. Je veux que le ListView mette à jour et montre cette modification. Normalement, il ne montre pas ce nouvel élément jusqu'à ce que je vais à l'écran d'accueil et rouvrir l'application.Android: comment utiliser CursorAdapter?

J'ai fini par le faire fonctionner en appelant cursor.requery() ou mCustomCursorAdapter.changeCursor(newCursor) chaque fois que j'ajouté un nouvel élément, mais quand je mets autoRequery false dans le constructeur CursorAdapter, cela a fonctionné exactement la même chose. Pourquoi est-il mis à jour correctement lorsque autoRequery est défini sur false? Je utilise correctement CursorAdapter? Quelle est la manière standard de maintenir la liste à jour avec la base de données? Et que fait autoRequery?

+0

@randzero signifie que vous souhaitez mettre à jour les éléments ListView chaque fois nouvel élément est ajouté dans la base de données , est ce bien ? –

Répondre

37

La manière idiomatique et imho correcte de mettre à jour automatiquement Cursor s est d'appeler Cursor#setNotificationUri quand ils sont créés et avant qu'ils soient remis à tout ce qui leur est demandé. Puis appelez ContentResolver#notifyChange lorsque quelque chose dans l'espace de noms de Cursor de Uri change. Par exemple, supposons que vous créiez une application de messagerie simple et que vous souhaitiez la mettre à jour lorsque de nouveaux messages arrivaient, mais que vous fournissiez également différents affichages sur le courrier. Je voudrais avoir des Uri de base définis.

content://org.example/all_mail 
content://org.example/labels 
content://org.example/messages 

Maintenant, disons que je voulais obtenir un curseur qui m'a donné tout le courrier et être mis à jour l'arrivée de nouveaux mail:

Cursor c; 
//code to get data 
c.setNotificationUri(getContentResolver(), Uri.parse("content://org.example/all_mail"); 

maintenant le nouveau courrier arrive donc je préviens:

//Do stuff to store in database 
getContentResolver().notifyChange(Uri.parse("content://org.example/all_mail", null); 

Je devrais également informer tous les Cursor s qui ont choisi pour les étiquettes ce nouveau message rencontré

for(String label : message.getLabels() { 
    getContentResolver().notifyChange(Uri.parse("content://org.example/lables/" + label, null); 
} 

Et aussi, peut-être un curseur visualise qu'un message spécifique afin de les informer ainsi:

getContentResolver().notifyChange(Uri.parse("content://org.example/messages/" + message.getMessageId(), null); 

Les getContentResolver() appels se produit lorsque les données sont accessibles. Donc, si c'est dans un Service ou ContentProvider c'est là que vous setNotificationUri et notifyChange. Vous ne devriez pas faire cela à partir de l'endroit où les données sont accédées, par exemple un Activity.

AlarmProvider est un ContentProvider simple qui utilise cette méthode pour mettre à jour Cursor s.

+1

C'était vraiment utile. Merci d'avoir partagé. –

+0

Ce message est vraiment génial! Ça m'a beaucoup aidé aussi lors de ma recherche! :) –

+0

Corrigez-moi si je me trompe 'Cursor # setNotificationUri' met à jour le curseur avec les dernières données chaque fois qu'un' getContentResolver(). NotifyChanged' est appelé dans 'ContentProvider'. –

1

J'ai créé la méthode suivante pour la mise à jour ListView:

/** 
* Method of refreshing Cursor, Adapter and ListView after database 
* changing 
*/ 
public void refreshListView() { 
    databaseCursor = db.getReadableDatabase().query(
      CurrentTableName, 
      null, 
      null, 
      null, 
      null, 
      null, 
      "title"+SortingOrder); 
    databaseListAdapter = new DomainAdapter(this, 
      android.R.layout.simple_list_item_2, 
      databaseCursor, 
      new String[] {"title", "description"}, 
      new int[] { android.R.id.text1, android.R.id.text2 }); 
    databaseListAdapter.notifyDataSetChanged(); 
    DomainView.setAdapter(databaseListAdapter); 
} 

fin appelle à chaque fois après un certain changement dans la base

Questions connexes