Je le garderais ouvert tout le temps et le fermerais dans une méthode de cycle de vie telle que onStop
ou onDestroy
. de cette façon, vous pouvez facilement vérifier si la base de données est déjà utilisée en appelant isDbLockedByCurrentThread
ou isDbLockedByOtherThreads
sur l' SQLiteDatabase
objet unique à chaque fois avant de l'utiliser. cela empêchera de multiples manipulations de la base de données et sauvera votre application d'un crash potentiel
donc dans votre singleton, vous pourriez avoir une méthode comme celle-ci pour obtenir votre seul SQLiteOpenHelper
objet:
private SQLiteDatabase db;
private MyDBOpenHelper mySingletonHelperField;
public MyDBOpenHelper getDbHelper() {
db = mySingletonHelperField.getDatabase();//returns the already created database object in my MyDBOpenHelper class(which extends `SQLiteOpenHelper`)
while(db.isDbLockedByCurrentThread() || db.isDbLockedByOtherThreads()) {
//db is locked, keep looping
}
return mySingletonHelperField;
}
donc chaque fois que vous souhaitez utiliser votre objet d'assistance ouvert, appelez cette méthode getter (assurez-vous qu'elle est filetée)
une autre méthode de votre singleton peut être (appelée CHAQUE FOIS avant d'essayer d'appeler le getter ci-dessus):
public void setDbHelper(MyDBOpenHelper mySingletonHelperField) {
if(null == this.mySingletonHelperField) {
this.mySingletonHelperField = mySingletonHelperField;
this.mySingletonHelperField.setDb(this.mySingletonHelperField.getWritableDatabase());//creates and sets the database object in the MyDBOpenHelper class
}
}
vous pouvez également fermer la base de données dans le singleton:
public void finalize() throws Throwable {
if(null != mySingletonHelperField)
mySingletonHelperField.close();
if(null != db)
db.close();
super.finalize();
}
si les utilisateurs de votre application ont la possibilité de créer très rapidement de nombreuses interactions de base de données, vous devez utiliser quelque chose comme je l'ai démontré ci-dessus. mais s'il y a des interactions minimales avec la base de données, je ne m'inquiéterais pas à ce sujet, et créer et fermer la base de données à chaque fois.
À partir de maintenant, il n'est pas nécessaire de vérifier si la base de données est verrouillée par un autre thread. Pendant que vous utilisez le singleton SQLiteOpenHelper dans chaque thread, vous êtes en sécurité. De la
isDbLockedByCurrentThread
documentation:isDbLockedByOtherThreads
est obsolète depuis le niveau d'API 16.la source
Concernant les questions:
Nous devrions diviser «ouverture DB», «ouverture d'une connexion». SQLiteOpenHelper.getWritableDatabase () donne une base de données ouverte. Mais nous n'avons pas à contrôler les connexions car cela se fait en interne.
Oui, ça l'est. Les connexions ne se bloquent pas si les transactions sont correctement fermées. Notez que votre BD sera également fermée automatiquement si GC la finalise.
La fermeture de l'instance SQLiteDatabase ne donne rien de formidable à part la fermeture des connexions, mais c'est mauvais pour un développeur s'il y a des connexions à ce moment. De plus, après SQLiteDatabase.close (), SQLiteOpenHelper.getWritableDatabase () renverra une nouvelle instance.
Non, il n'y en a pas. Notez également que la fermeture de la base de données à un moment et un thread sans rapport, par exemple dans Activity.onStop (), peut fermer les connexions actives et laisser les données dans un état incohérent.
la source
Android 8.1 a une
SQLiteOpenHelper.setIdleConnectionTimeout(long)
méthode qui:https://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#setIdleConnectionTimeout(long)
la source
Du point de vue des performances, la manière optimale est de conserver une seule instance de SQLiteOpenHelper au niveau de l'application. L'ouverture de la base de données peut être coûteuse et constitue une opération de blocage, elle ne doit donc pas être effectuée sur le thread principal et / ou dans les méthodes du cycle de vie de l'activité.
La méthode setIdleConnectionTimeout () (introduite dans Android 8.1) peut être utilisée pour libérer de la RAM lorsque la base de données n'est pas utilisée. Si le délai d'inactivité est défini, la ou les connexions à la base de données seront fermées après une période d'inactivité, c'est-à-dire lorsque la base de données n'a pas été accédée. Les connexions seront rouvertes de manière transparente avec l'application, lorsqu'une nouvelle requête est exécutée.
En plus de cela, une application peut appeler releaseMemory () lorsqu'elle passe en arrière-plan ou détecte une pression mémoire, par exemple dans onTrimMemory ()
la source
Vous pouvez également utiliser ContentProvider. Il fera cela pour vous.
la source
Créez votre propre contexte d'application, puis ouvrez et fermez la base de données à partir de là. Cet objet possède également une méthode OnTerminate () que vous pouvez utiliser pour fermer la connexion. Je ne l'ai pas encore essayé, mais cela semble être une meilleure approche.
@binnyb: Je n'aime pas utiliser finalize () pour fermer la connexion. Cela pourrait fonctionner, mais d'après ce que j'ai compris, écrire du code dans une méthode Java finalize () est une mauvaise idée.
la source
onTerminate
cela ne sera pas appelé dans un environnement de production - developer.android.com/reference/android/app/...