Cette question est un peu ancienne mais elle est toujours d'actualité. Notez que si vous faites les choses de la manière "moderne" (par exemple en utilisant LoaderManager et en créant des CursorLoaders pour interroger un ContentProvider en arrière-plan), assurez-vous que vous n'appelez PAS db.close() dans votre implémentation du ContentProvider. J'obtenais toutes sortes de plantages liés à CursorLoader/AsyncTaskLoader quand il essayait d'accéder au ContentProvider dans un thread d'arrière-plan, qui ont été résolus en supprimant les appels db.close().
Donc si vous rencontrez des plantages qui ressemblent à ça (Jelly Bean 4.1.1) :
Caused by: java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962)
at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:677)
at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348)
at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:834)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)
at android.content.ContentResolver.query(ContentResolver.java:388)
at android.content.ContentResolver.query(ContentResolver.java:313)
at com.hindsightlabs.paprika.loaders.GroceryListLoader.loadInBackground(GroceryListLoader.java:147)
at com.hindsightlabs.paprika.loaders.GroceryListLoader.loadInBackground(GroceryListLoader.java:1)
at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240)
at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51)
at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40)
at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
... 4 more
Ou ceci (ICS 4.0.4) :
Caused by: java.lang.IllegalStateException: database /data/data/com.hindsightlabs.paprika/databases/Paprika.db (conn# 0) already closed
at android.database.sqlite.SQLiteDatabase.verifyDbIsOpen(SQLiteDatabase.java:2215)
at android.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:436)
at android.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:422)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:79)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:164)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:156)
at android.content.ContentResolver.query(ContentResolver.java:318)
at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:49)
at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:35)
at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240)
at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51)
at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40)
at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
... 4 more
Ou si vous voyez des messages d'erreur dans LogCat qui ressemblent à ceci :
Cursor: invalid statement in fillWindow()
Vérifiez ensuite l'implémentation de votre ContentProvider et assurez-vous que vous ne fermez pas la base de données prématurément. D'après ce En effet, le ContentProvider sera de toute façon nettoyé automatiquement lorsque le processus sera tué. Il n'est donc pas nécessaire de fermer sa base de données à l'avance.
Cela dit, assurez-vous que vous êtes toujours correctement :
- Fermer vos curseurs qui sont retournés par ContentProvider.query() . (CursorLoader/LoaderManager fait cela automatiquement pour vous, mais si vous faites des requêtes directes en dehors du cadre de LoaderManager, ou si vous avez implémenté une sous-classe personnalisée de CursorLoader/AsyncTaskLoader, vous devrez vous assurer que vous nettoyez vos curseurs correctement).
- Implémentation de votre ContentProvider de manière sécurisée. (La façon la plus simple de le faire est de s'assurer que vos méthodes d'accès à la base de données sont enveloppées dans un fichier de type synchronisé bloc.)