web-dev-qa-db-fra.com

android - CursorLoader & SQLite sans fournisseur de contenu

Je sais que cela a été discuté pourtant je voulais poser des questions sur l'état actuel de la question. Dois-je créer un ContentProvider pour utiliser CursorLoader en connexion avec une base de données sqlite?

J'ai trouvé

tilisation de CursorLoader sans ContentProvider

Regarde exactement ce que j'espérais encore comme l'a commenté Emmby

  • Les utilisateurs doivent être conscients d'une limitation, à savoir qu'il n'a aucun mécanisme pour actualiser les modifications de données (comme les chargeurs sont censés le faire)

Donc, une autre solution est mentionnée

https://github.com/commonsguy/cwac-loaderex

encore une fois, un inconvénient est souligné

  • Cependant, pour utiliser la réinterrogation automatique, vous devez utiliser le même chargeur pour l'interface utilisateur ainsi que pour les mises à jour, ce qui limite son utilisation pour les services d'arrière-plan.

Bien sûr, lorsque vous utilisez LoaderManager, nous voulons obtenir tous les avantages pour lesquels il a été introduit. Ma question est donc de savoir s'il existe un moyen d'utiliser LoaderManager en connexion avec une base de données sqlite sans avoir à implémenter un fournisseur de contenu tout en ayant tous les avantages.

Merci

54
dorjeduck

Les deux implémentations que vous mentionnez dans votre article offrent toutes les avantages de CursorLoader sauf la possibilité de recevoir des notifications lorsque le contenu sous-jacent changements.

Je me suis beaucoup penché sur la question récemment et je peux vous dire en toute confiance que l'API Android actuellement ne fournit pas de moyen de le faire avec uniquement un SQLiteDatabase brut (il fournit uniquement les méthodes ContentResolver#notifyChange() et Cursor#setNotificationUri(), qui sont utilisées pour notifier tous les Cursor enregistrés sous une certaine notification Uri).

Cela dit, vos options en ce moment sont les suivantes:

  1. Implémentez vous-même un observateur qui est capable de recevoir des notifications de SQLiteDatabase lorsque le contenu change, et qui est en quelque sorte en mesure de relayer ces notifications à tous les Loaders existants dans votre application. J'ai écrit un article de blog assez complet sur la façon d'implémenter Loaders qui pourrait être utile si vous le souhaitez pour relever ce défi. Ou...

  2. Utilisez la bibliothèque LoaderEx de Mark Murphy et n'effectuez des modifications de base de données qu'en utilisant les opérations AsyncTask fournies par sa bibliothèque. Notez que la raison pour laquelle ses tâches actualisent le Loader est qu'elles appellent onContentChanged sur le Loader immédiatement après l'insertion/la mise à jour/la suppression, ce qui indique effectivement au Loader que le contenu a changé et qu'il doit actualiser ses données.

  3. Utilisez simplement un ContentProvider avec un CursorLoader et vous pouvez utiliser la méthode ContentResolver#notifyChange() pour informer le CursorLoader qu'un changement de contenu s'est produit.

J'essaie de trouver une meilleure solution, et je ferai rapport à l'avenir si j'en trouve/mets en œuvre une, mais pour l'instant, cela devra faire.

66
Alex Lockwood

Voici ma solution, dans mon onCreateLoader

{
Uri u = Uri.parse("content://what_string_you_want");
return new CursorLoader(this, yourURI, projection, null, null, null) {
    private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();

    @Override
    public Cursor loadInBackground() {
        Cursor c = YOUR_DATABASE.doYourQuery(...);
        if (c != null) {
          // Ensure the cursor window is filled
           c.getCount();
           c.registerContentObserver(mObserver);
        }

        c.setNotificationUri(getContext().getContentResolver(), getUri());
        return c;
    }
};
}

Après le code qui changera la base de données, ajoutez

 getContentResolver().notifyChange(
            Uri.parse("content://same_with_first_string"), null);
2
Dev Ngo