Solución:
Lo mantendría abierto todo el tiempo y lo cerraría en algún método de ciclo de vida como onStop
o onDestroy
. de esa manera, puede verificar fácilmente si la base de datos ya está en uso llamando isDbLockedByCurrentThread
o isDbLockedByOtherThreads
en el single SQLiteDatabase
objeto cada vez antes de usarlo. esto evitará múltiples manipulaciones en la base de datos y salvará su aplicación de un posible bloqueo
así que en tu singleton, es posible que tengas un método como este para obtener tu single SQLiteOpenHelper
objeto:
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;
}
así que siempre que desee utilizar su objeto auxiliar abierto, llame a este método getter (asegúrese de que esté enhebrado)
otro método en su singleton puede ser (llamado CADA VEZ antes de intentar llamar al getter anterior):
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
}
}
es posible que también desee cerrar la base de datos en el singleton:
public void finalize() throws Throwable {
if(null != mySingletonHelperField)
mySingletonHelperField.close();
if(null != db)
db.close();
super.finalize();
}
Si los usuarios de su aplicación tienen la capacidad de crear muchas interacciones con la base de datos muy rápidamente, debe usar algo como lo he demostrado anteriormente. pero si hay interacciones mínimas con la base de datos, no me preocuparía por eso y solo crearía y cerraría la base de datos cada vez.
A partir de ahora, no es necesario verificar si la base de datos está bloqueada por otro hilo. Mientras usa singleton SQLiteOpenHelper en cada hilo, está seguro. De isDbLockedByCurrentThread
documentación:
El nombre de este método proviene de un momento en el que tener una conexión activa a la base de datos significaba que el hilo tenía un bloqueo real en la base de datos. Hoy en día, ya no existe un verdadero “bloqueo de base de datos”, aunque los subprocesos pueden bloquearse si no pueden adquirir una conexión de base de datos para realizar una operación en particular.
isDbLockedByOtherThreads
está en desuso desde el nivel de API 16.
Respecto a las preguntas:
Mi administrador de base de datos es un singleton y en este momento abre una conexión a la base de datos cuando se inicializa.
Deberíamos dividir ‘abrir DB’, ‘abrir una conexión’. SQLiteOpenHelper.getWritableDatabase () da una base de datos abierta. Pero no tenemos que controlar las conexiones como se hace internamente.
¿Es seguro dejar la base de datos abierta todo el tiempo para que cuando alguien llame a mi clase para trabajar con la base de datos ya esté abierta?
Sí lo es. Las conexiones no se cuelgan si las transacciones se cierran correctamente. Tenga en cuenta que su base de datos también se cerrará automáticamente si GC la finaliza.
¿O debo abrir y cerrar la base de datos antes y después de que se necesite cada acceso?
Cerrar la instancia de SQLiteDatabase no da nada tremendo excepto cerrar conexiones, pero esto es malo para un desarrollador si hay algunas conexiones en este momento. Además, después de SQLiteDatabase.close (), SQLiteOpenHelper.getWritableDatabase () devolverá una nueva instancia.
¿Hay algún daño en dejarlo abierto todo el tiempo?
No, no lo hay. Tenga en cuenta también que cerrar la base de datos en un momento y subproceso no relacionados, por ejemplo, en Activity.onStop () podría cerrar las conexiones activas y dejar los datos en un estado inconsistente.