2

Nous stockons une copie de l'état du serveur de certains éléments localement dans notre application. Lorsque nous recevons de nouvelles données du serveur, les éléments peuvent avoir été modifiés, supprimés ou insérés. Lorsque les données sont synchronisées, toutes les données actuelles sont extraites du serveur.Synchronisation de la base de données SQLite sans provoquer plusieurs onChange

Liste locale:
Point 1, les progrès 23
Point 2, progrès 75
Point 3, les progrès 88

Liste à distance: (article 2 a été supprimé)
Point 1, Progrès 55
Point 3, progression 88
Point 4, progression 1 (NOUVEAU)

La solution actuelle efface la table, puis insère en bloc tous les éléments de ce type:

// Remove old content (this is to prevent dead items being left) 
    mContentResolver.delete(URI_TO_TABLE, null, null); 

    // Insert all new items 
    // Most existing items are changed in a sync, hence we may just insert them again instead of updating 
    final ContentValues[] inserts = new ContentValues[newItems.size()]; 
    for (int i = 0; i < newItems.size(); i++) { 
     inserts[i] = getChallengeContentValues(newItems.get(i)); 
    } 
    mContentResolver.bulkInsert(URI_TO_TABLE, inserts); 

Le problème ici est que nous utilisons également un ContentObserver, qui envoie deux onChange() chaque fois (un pour supprimer et un pour bulkInsert), ce qui provoque notre interface utilisateur à la première mise à jour lorsque la table est effacée, vider notre liste d'éléments, et directement après la mise à jour avec la liste fraîchement synchronisée, peupler la vue à nouveau. Cela provoque beaucoup de vilain clignotement.

Y a-t-il un moyen pour en obtenir un onChange()? Le applyBatch() semble générer un onChange() par opération. Pouvez-vous dire en quelque sorte à ContentProvider de menacer un tas de mises à jour comme une seule? OU Y at-il une autre façon de prendre la nouvelle liste (à distance) et de la stocker dans la base de données?

Répondre

0

Comme vous l'avez mentionné applyBatch() est la bonne façon de le faire. Créez ContentProviderOperation pour chacune de vos transactions d'ajout/de mise à jour/de suppression, stockez-les en tant que ArrayList<ContentProviderOperation> operations et exécutez-les comme une seule opération applyBatch().

http://developer.android.com/reference/android/content/ContentProvider.html#applyBatch%28java.util.ArrayList%3Candroid.content.ContentProviderOperation%3E%29

Si votre table est énorme et que vous ne voulez pas avoir les frais généraux de applyBatch() et le besoin doit utiliser bulkInsert() alors vous pourriez ajouter une sorte de hack comme l'ajout d'une supplémentaire dans la requête de suppression serait éclaireraient la le fournisseur ne doit pas déclencher notifyDataSetChanged()