¿Cuán cuidado debo tener con el hilo de seguridad al crear métodos / actividades que interactúan con la base de datos SQLite?
Estoy creando una aplicación que permite que muchas Activities
diferentes se inicie desde una TabActivity
(hasta ~ 25). La mayoría de las actividades requieren datos de la base de datos sqlite, por lo que cuando onCreate
se ejecuta, AsyncTask
crea un objeto SQLiteOpenHelper (que abrirá una base de datos legible / grabable), ejecuta una consulta, recupera los datos y todo se cierra.
Solo estaba probando el desorden para ver si podía romper algo, así que TabActivity's
cada Activity
a la TabActivity's
TabHost
. Entonces comencé a machacar cada lengüeta lo más rápidamente posible.
- Error al leer la fila 0, columna 0 de una CursorWindow que tiene 0 filas, 64 columnas
- ¿Cómo agregar una nueva columna a la base de datos SQLite de Android?
- Mejor alternativa de la librería Android de SQLite?
- Prácticas recomendadas para exponer varias tablas mediante proveedores de contenido en Android
- Cómo almacenar y recuperar una matriz de bytes (datos de imagen) ay desde una base de datos SQLite?
Me di cuenta de que muy rápidamente comencé a ver en el LogCat: Caused by: android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE;
Y la aplicación procedió a morir.
Normalmente sólo habrá alrededor de 4-6 pestañas (sólo puedo limitar el usuario de todos modos) para el TabHost
. No he sido capaz de romper nada con una pequeña cantidad de pestañas para aplastar, pero todavía estoy preocupado de que tal vez estoy accediendo a la base de datos de una manera pobre.
¿Cómo puedo evitar que mis objetos de SQLiteDatabase provoquen un bloqueo?
Si creo un ContentProvider
que eliminará la posibilidad de bloqueo de base de datos?
¿Tiene alguna sugerencia para los cambios que podría hacer para acceder a los datos de una SQLiteDatabase
datos SQLiteDatabase
?
Terminé tomando el acercamiento de usar la clase de la Application
y de almacenar 1 SQLiteOpenHelper
y de intentar mi mejor para guardarlo sincronizado. Esto parece estar funcionando muy bien – pongo todas mis 25 actividades en TabHost
y aplastadas en ellas sin errores.
Estoy llamando ((SQLiteDbApplication)getApplication()).setDbHelper(new DBHelper(this, Constants.DB_NAME, null, Constants.DB_VERSION_CODE));
Método (mostrado abajo) en cada onCreate()
en mis actividades
¿Alguna otra sugerencia para este enfoque o para los cambios que hice usando esta clase de Application
?
import android.app.Application; import android.database.sqlite.SQLiteDatabase; public class SQLiteDbApplication extends Application { private DBHelper dbHelper; private SQLiteDatabase db; public synchronized DBHelper getDbHelper() { db = dbHelper.getDatabase();//returns the already opened database object while(db.isDbLockedByCurrentThread() || db.isDbLockedByOtherThreads()); return dbHelper; } public synchronized void closeDb() { if(null != dbHelper) dbHelper.close(); if(null != db) db.close(); } @Override protected void finalize() throws Throwable { if(null != dbHelper) dbHelper.close(); if(null != db) db.close(); super.finalize(); } public synchronized void setDbHelper(DBHelper dbHelper) { if(null == this.dbHelper) { this.dbHelper = dbHelper; this.dbHelper.setDb(this.dbHelper.getWritableDatabase());//creates and sets the database object via getWritableDatabase() } } }
- Uso correcto de Sqlite en Android (SQLiteOpenHelper, conexiones, hilo principal, etc ...)
- por qué c.moveToFirst () no saltará la primera fila
- ¿Cómo puedo simular una actualización de la aplicación?
- Error al abrir la base de datos / Error al cambiar la configuración regional de (base de datos) a 'en_US'
- Razones para utilizar la base de datos SQLite legible
- SQLite demasiados términos en SELECT compuesto
- Cómo restringir la base de datos sqlite abierta en el proyecto de la biblioteca de Android mientras crea el archivo jar
- GreenDao consultas profundas con relaciones n: m
Si usted está preocupado por todas las conexiones de la base de datos tratar de limitarse a un SqliteOpenHelper y asegúrese de envolver una capa de sincronización a su alrededor.
Puede extender la clase de aplicación y luego llamar a getApplication y lanzar el objeto que obtenga en su aplicación. Ahora puede almacenar un SqliteOpenHelper en esta clase de aplicación y crear su propio método de acceso seguro de subproceso a la conexión de base de datos.
Si está utilizando AsyncTask en todos sus métodos onCreate y tiene problemas con muchas pestañas, estos problemas también pueden ocurrir con un dispositivo más lento, un usuario más rápido o una base de datos que crece durante el tiempo de uso.
Dependiendo del caso de uso de su aplicación, puede ir a la manera de guardar y pasar por todo el esfuerzo y el dolor de roscar y bloqueo, o simplemente puede publicar la aplicación con un número de pestañas que nunca produjo el error y asegúrese de coger el Base de datos y envíese una notificación (por ejemplo a través de Google Analytics) para probar si el problema de subprocesos ocurre en el uso de la aplicación en la vida real.
Todas las devoluciones de llamadas de la actividad ocurren en el hilo principal, por lo que en el escenario que describe no hay multi-threading en marcha, no importa cuántas actividades o pestañas que tiene.
ContentProvider no proporciona ningún bloqueo. De hecho, puede introducir multithreading donde no lo tendría ya porque permite que otros procesos realicen llamadas en su propio proceso y cuando eso ocurre la llamada se envía desde un hilo separado en su proceso (no en la interfaz de usuario principal hilo).
Por supuesto, si usted crea sus propios hilos, entonces también tendrá multi-threading en curso.
- Puedo escalar el emulador de genymotion a "tamaño real del dispositivo"?
- Cómo hacer que la aplicación de Android se comunique con db de MySQL externo