27 votes

Est-il acceptable d’avoir un cas de SQLiteOpenHelper partagé par toutes les activités dans une application Android?

Serait-il acceptable d’avoir une seule instance de SQLiteOpenHelper en tant que membre d’une application sous-classée, et avoir toutes les activités qui ont besoin d’une instance de SQLiteDatabase l’obtenir à partir d’un seul assistant?

36voto

Alex Lockwood Points 31578

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

CommonsWare, c'est sur (comme d'habitude). L'expansion sur son post, 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: sous-classement "Application"

Si vous savez que votre application ne sera pas très compliqué (c'est à dire si vous savez que vous ne finissent par en avoir une sous-classe de la Application), alors vous pouvez créer une sous-classe de Application et votre principale Activité de l'étendre. Cela garantit qu'une instance de la base de données est en cours d'exécution tout au long de l'Application de l'ensemble du cycle de vie.

public class MainApplication extends Application {

    /**
     * see NotePad tutorial for an example implementation of DataDbAdapter
     */
    private static DataDbAdapter mDbHelper;

    /**
     * Called when the application is starting, before any other 
     * application objects have been created. Implementations 
     * should be as quick as possible...
     */
    @Override
    public void onCreate() {
        super.onCreate();
        mDbHelper = new DataDbAdapter(this);
        mDbHelper.open();
    }

    public static DataDbAdapter getDatabaseHelper() {
        return mDbHelper;
    }
}

Approche n ° 2: 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://developer.android.com/resources/articles/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 ° 3: 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 LoaderManager classe s'appuie fortement sur ContentProviders, donc si vous voulez une Activité ou d'un Fragment de mettre en œuvre LoaderManager.LoaderCallbacks<Cursor> (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 ça aide!

24voto

CommonsWare Points 402670

Avoir un seul SQLiteOpenHelper instance peut aider dans le filetage des cas. Depuis tous les threads partagent la commune SQLiteDatabase, la synchronisation des opérations est fournie.

Cependant, je ne voudrais pas faire une sous-classe de Application. Juste une donnée membre statique qui est votre SQLiteOpenHelper. Les deux approches vous donner quelque chose d'accessible à partir de n'importe où. Toutefois, il existe une sous-classe de la Application, rendant plus difficile pour vous d'utiliser d'autres sous-classes de Application (par exemple, GreenDroid nécessite un IIRC). À l'aide d'une donnée membre statique évite que. Néanmoins, utilisez l' Application Context lors de l'instanciation de cette statique SQLiteOpenHelper (paramètre du constructeur), de sorte que vous n'avez pas de fuite de certains autres Context.

Et, dans le cas où vous n'êtes pas affaire avec plusieurs threads, vous pouvez éviter d'éventuels problèmes de fuite de mémoire en utilisant simplement un SQLiteOpenHelper exemple par composant. Cependant, dans la pratique, vous devriez traiter avec plusieurs threads (par exemple, un Loader), de sorte que cette recommandation n'est pertinente que pour trivial applications, tels que ceux trouvés dans des livres... :-)

7voto

d4rxh4wx Points 71

J'ai écrit MultiThreadSQLiteOpenHelper qui est une amélioration de SQLiteOpenHelper pour les applications Android, où plusieurs threads peut ouvrir et fermer de la même base de données sqlite.

Au lieu d'appeler à proximité de la méthode, les threads demander la fermeture de la base de données, la prévention d'un thread d'exécution d'une requête sur un fermé de la base de données.

Si chaque thread a demandé la fermeture, puis un gros est effectivement réalisé. Chaque activité ou du fil (ui-fil et de l'utilisateur-threads) effectue un appel ouvert sur la base de données lors de la reprise, et demande la fermeture de la base de données lors de la suspension ou de la finition.

Le code Source et les échantillons disponibles ici: https://github.com/d4rxh4wx/MultiThreadSQLiteOpenHelper

1voto

coder_For_Life22 Points 8908

Oui, c’est la façon dont vous devriez vous y prendre, ayant une classe d’aide pour les activités qui ont besoin d’une instance de la base de données.

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