Función SQLiteDatabase close () que causa NullPointerException cuando varios subprocesos

Descubrí en mi proyecto que la función close () en la implementación de SQLiteDatabase en Android arroja una NullPointerException al ejecutar múltiples hilos que abren la base de datos, insertan datos y luego cierran la base de datos. Todo funciona sin problemas a menos que permita que cada subproceso se cierre () después de insertarlo en la base de datos.

Aquí hay un ejemplo de cómo se vería uno de los hilos de escritura

ContentValues values = new ContentValues(); values.put(CallDetailsStorageConstants.COLUMN_NAME_REMOTE_NAME_IDX, (String) ""); values.put(CallDetailsStorageConstants.COLUMN_NAME_REMOTE_MEETINGID_IDX, (String) ""); CalculonDatabase callDetailsOpenHelper = CalculonDatabase.getInstance(mContext); SQLiteDatabase dbw = callDetailsOpenHelper.getWritableDatabase(); long rowid = 0; try { rowid = dbw.insertWithOnConflict(CallDetailsTable.CALL_DETAILS_TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); } catch (SQLiteConstraintException e) { e.printStackTrace(); } finally { dbw.close(); } 

Puede ver que al final se realiza una llamada para cerrar (). Cuando ejecuto varios hilos obtengo esta excepción.

 11-03 03:39:26.128: E/AndroidRuntime(977): FATAL EXCEPTION: Thread-17 11-03 03:39:26.128: E/AndroidRuntime(977): java.lang.NullPointerException 11-03 03:39:26.128: E/AndroidRuntime(977): at android.database.sqlite.SQLiteStatement.releaseAndUnlock(SQLiteStatement.java:283) 11-03 03:39:26.128: E/AndroidRuntime(977): at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:96) 11-03 03:39:26.128: E/AndroidRuntime(977): at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1933) 11-03 03:39:26.128: E/AndroidRuntime(977): at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1864) 11-03 03:39:26.128: E/AndroidRuntime(977): at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:636) 11-03 03:39:26.128: E/AndroidRuntime(977): at android.database.sqlite.SQLiteDatabase.beginTransactionNonExclusive(SQLiteDatabase.java:551) 11-03 03:39:26.128: E/AndroidRuntime(977): at android.database.sqlite.SQLiteStatement.acquireAndLock(SQLiteStatement.java:240) 11-03 03:39:26.128: E/AndroidRuntime(977): at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:111) 11-03 03:39:26.128: E/AndroidRuntime(977): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1737) 11-03 03:39:26.128: E/AndroidRuntime(977): at com.smash.DBWritingThread.run(DBWritingThread.java:50) 

Mi pregunta es, ¿por qué este error ocurre solo cuando se usa la función close ()? Además, ¿está bien usar close () mucho más tarde o posiblemente nunca?

Cualquier consejo con este tema es muy apreciado.

¡Tengo tus respuestas!

Nunca cierre el db. Es así de simple.

Asegúrese de tener solo una, repetición, * una instancia de Ayudante por aplicación. Compártalo con todos los hilos.

http://www.touchlab.co/blog/single-sqlite-connection/

Aquí hay más información sobre las partes internas de sqlite y locking:

http://www.touchlab.co/blog/android-sqlite-locking/

No necesitas molestarte. Consulte esta discusión que incluye la confirmación de que el sistema cierra la base de datos según sea necesario si / cuando el proceso se cancela.

La cita relevante, de un empleado de Google, es:

Se crea un proveedor de contenido cuando se crea su proceso de alojamiento, y se mantiene durante todo el tiempo que dure el proceso, por lo que no es necesario cerrar la base de datos ; se cerrará como parte del kernel limpiando los recursos del proceso cuando el proceso es asesinado.

Si está trabajando directamente en una base de datos SQLite sin recurrir a un proveedor de contenido, un patrón que he visto utilizar es cerrar la base de datos en Application.onTerminate , mientras que la instancia Application almacena el “adaptador” de la base de datos singleton, que sería un objeto que contiene una SQLiteDatabase y su SQLiteOpenHelper .

Parece similar a este problema: la función SQLiteDatabase close () causa NullPointerException cuando varios subprocesos

Es posible que no necesite llamar a database.close ()