82 votes

À l'aide de modèle de conception Singleton pour SQLiteDatabase

Je suis plutôt novice sur Android, et je suis en train de travailler sur une application simple pour obtenir une certaine expérience de base. Mon application est assez simple et se compose entre autres d'un récepteur de radiodiffusion et de certaines activités. Les deux composants, l'utilisation d'une base de données unique, donc, en théorie, il pourrait arriver que les deux essayer d'accéder à la db en même temps.

Actuellement, je suis tout simplement l'instanciation de la db objet (qui est-SQLite db classe helper) à chaque fois que j'en ai besoin, et d'effectuer les opérations nécessaires: requête, insert, etc.

De ce que j'ai lu ici et dans d'autres documents, ce qui a le problème de l'obtention d'un "db verrouillé" exception dans le cas où la base de données est accessible simultanément, donc une meilleure approche serait d'avoir une seule instance de cette db objet afin que tous les composants utilisent la même connexion db à tout moment.

Est le raisonnement ci-dessus est correcte? Serait un singleton alors être une bonne solution pour cela? Je sais que certains puristes peut faire valoir contre elle, mais s'il vous plaît noter que ceci est un peu simple demande si je peux me permettre de faire des choses que je ne serait pas dans d'autres cas.

Sinon, ce serait une meilleure option? J'ai lu sur l'utilisation de fournisseur de contenu, mais il serait trop pour cela, outre que je ne suis pas intéressé pour partager les données avec d'autres activités. J'ai en effet lu ce post et trouvé ça plutôt utile.

Merci à l'avance.

102voto

Alex Lockwood Points 31578

Cliquez ici pour voir mon billet de blog sur ce sujet.

Voici un exemple de code qui illustre trois approches possibles. Ceux-ci permettront l'accès à la base de données dans l'application.

Approche n ° 1: avoir " SQLiteOpenHelper` être une donnée membre statique

Ce n'est pas la mise en œuvre complète, mais elle devrait vous donner une bonne idée sur la façon d'aller sur la conception de l' DatabaseHelper classe correctement. La statique de l'usine méthode garantit qu'il n'existe qu'un DatabaseHelper instance à tout moment.

/**
 * create custom DatabaseHelper class that extends SQLiteOpenHelper
 */
public class DatabaseHelper extends SQLiteOpenHelper { 
    private static DatabaseHelper mInstance = null;

    private static final String DATABASE_NAME = "databaseName";
    private static final String DATABASE_TABLE = "tableName";
    private static final int DATABASE_VERSION = 1;

    private Context mCxt;

    public static DatabaseHelper getInstance(Context ctx) {
        /** 
         * use the application context as suggested by CommonsWare.
         * this will ensure that you dont accidentally leak an Activitys
         * context (see this article for more information: 
         * http://android-developers.blogspot.nl/2009/01/avoiding-memory-leaks.html)
         */
        if (mInstance == null) {
            mInstance = new DatabaseHelper(ctx.getApplicationContext());
        }
        return mInstance;
    }

    /**
     * constructor should be private to prevent direct instantiation.
     * make call to static factory method "getInstance()" instead.
     */
    private DatabaseHelper(Context ctx) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.mCtx = ctx;
    }
}

Approche n ° 2: résumé de la base de données SQLite avec un " ContentProvider`

C'est l'approche que je ne le suggèrent. Pour l'un, le nouveau CursorLoader classe exige ContentProviders, donc si vous voulez une Activité ou d'un Fragment de mettre en œuvre LoaderManager.LoaderCallbacks<Cursor> avec un CursorLoader (qui je vous suggère de prendre avantage de, il est magique!), vous aurez besoin de mettre en œuvre un ContentProvider pour votre application. De plus, vous n'avez pas besoin de vous soucier de faire un Singleton base de données helper avec ContentProviders. Appelez simplement getContentResolver() de l'Activité et le système se chargera de tout pour vous (en d'autres termes, il n'est pas nécessaire pour la conception d'un pattern Singleton pour empêcher plusieurs instances en cours de création).

Espérons que cette aide!

22voto

Snicolas Points 19644

Je n'ai jamais lu sur l'utilisation d'un singleton pour accéder à une base de données sur android. Pourriez-vous fournir un lien à ce sujet.

Dans mes applications, j'utilise simple dbhelper des objets, pas des singletons, je me disais que c'est plus le travail du moteur sql pour assurer la db n'est pas verrouillé, pas le travail de votre android classes, et il fonctionne très bien pour mon plus grand app qui est de taille moyenne.

Mise à jour #1: en regardant la référence que vous avez donné, il semble que le problème n'est pas du tout sur l'utilisation de différentes instances de l' dbhelper. Même une seule instance pourrait rencontrer des problèmes d'accès à des bases de données : le problème vient d'un accès simultanés. Donc le seul moyen d'assurer un bon accès à la base de données par différents threads est à utiliser de simples mécanismes de synchronisation de thread (synchronized méthodes ou des blocs), et c'est presque rien à faire avec l'aide d'un singleton.

Mise à jour #2 : le deuxième lien que vous fournissez montre clairement que leur est une nécessité pour singleton dbhelper objets dans le cas de plusieurs threads écrit en même temps dans un db. Cela peut arriver si vous ne vous en opérations sql (insertions, mises à jour et suppressions) de AsyncTasks par exemple. Dans ce cas, un objet singleton dbhelper serait tout simplement de mettre toutes les opérations sql dans une sorte de pipeline et de les exécuter dans l'ordre.

Cette solution pourrait être plus facile à mettre en œuvre en utilisant la bonne synchronisation de thread synchronisées à l'aide de méthodes en java. En fait je pense qu'il devrait y avoir plus de souligner quelque part dans android docs sur ce problème et l'utilisation d'un singleton db helper pourrait être encouragé.

Merci pour cette belle question et le suivi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X