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 SQLiteDatabase
objeto individual cada vez que lo use. esto evitará múltiples manipulaciones en la base de datos y salvará su aplicación de un posible bloqueo
por lo que en su singleton, es posible que tenga un método como este para obtener su único 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 que 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. Si bien usa singleton SQLiteOpenHelper en cada hilo, está seguro. De la
isDbLockedByCurrentThread
documentación:isDbLockedByOtherThreads
está en desuso desde el nivel de API 16.fuente
Respecto a las preguntas:
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.
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.
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.
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.
fuente
Android 8.1 tiene un
SQLiteOpenHelper.setIdleConnectionTimeout(long)
método que:https://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#setIdleConnectionTimeout(long)
fuente
Desde la perspectiva del rendimiento, la forma óptima es mantener una única instancia de SQLiteOpenHelper en el nivel de la aplicación. La apertura de la base de datos puede ser costosa y es una operación de bloqueo, por lo que no debe realizarse en el hilo principal y / o en los métodos del ciclo de vida de la actividad.
setIdleConnectionTimeout () método (introducido en Android 8.1) se puede usar para liberar RAM cuando no se usa la base de datos. Si se establece el tiempo de espera inactivo, las conexiones de la base de datos se cerrarán después de un período de inactividad, es decir, cuando no se haya accedido a la base de datos. Las conexiones se volverán a abrir de forma transparente a la aplicación cuando se ejecute una nueva consulta.
Además de eso, una aplicación puede llamar a releaseMemory () cuando pasa a segundo plano o detecta presión de memoria, por ejemplo, en onTrimMemory ()
fuente
También puede utilizar ContentProvider. Hará estas cosas por ti.
fuente
Cree su propio contexto de aplicación, luego abra y cierre la base de datos desde allí. Ese objeto también tiene un método OnTerminate () que puede usar para cerrar la conexión. No lo he probado todavía, pero parece un mejor enfoque.
@binnyb: No me gusta usar finalize () para cerrar la conexión. Podría funcionar, pero por lo que entiendo, escribir código en un método finalize () de Java es una mala idea.
fuente
onTerminate
no se llamará en un entorno de producción - developer.android.com/reference/android/app/…