Diese Frage ist ein bisschen alt, aber immer noch ziemlich relevant. Beachten Sie, dass Sie, wenn Sie Dinge auf "moderne" Art und Weise tun (z. B. LoaderManager verwenden und CursorLoaders erstellen, um einen ContentProvider in einem Hintergrundthread abzufragen), sicherstellen, dass Sie db.close() NICHT in Ihrer ContentProvider-Implementierung aufrufen. Ich habe alle Arten von Abstürzen im Zusammenhang mit CursorLoader/AsyncTaskLoader bekommen, als ich versuchte, auf den ContentProvider in einem Hintergrundthread zuzugreifen, die durch Entfernen der db.close() - Aufrufe gelöst wurden.
Also, wenn Sie in Abstürze laufen lassen, die wie folgt aussehen (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
Oder diese (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
Oder wenn Sie Fehlermeldungen in LogCat sind zu sehen, die wie folgt aussehen:
Cursor: invalid statement in fillWindow()
Dann Ihre Content Implementierung überprüfen und sicherzustellen, dass Sie die Datenbank nicht vorzeitig geschlossen wird. Gemäß this wird der ContentProvider automatisch bereinigt, wenn der Prozess trotzdem beendet wird, sodass Sie die Datenbank nicht vorzeitig schließen müssen.
Das heißt, stellen Sie sicher, Sie sind immer noch richtig:
- Ihre Cursoren Closing, die von ContentProvider.query() zurückgegeben werden. (CursorLoader/LoaderManager erledigt dies automatisch für Sie. Wenn Sie jedoch direkte Abfragen außerhalb des LoaderManager-Frameworks durchführen oder eine benutzerdefinierte CursorLoader/AsyncTaskLoader-Unterklasse implementiert haben, müssen Sie sicherstellen, dass Sie Ihre Cursor bereinigen richtig.)
- Implementieren Sie Ihren ContentProvider auf thread-sichere Weise. (Der einfachste Weg, dies zu tun ist, Ihre Datenbank-Zugriffsmethoden, um sicherzustellen, eingewickelt in einem synchronisiert Block.)
Dianne Hackborn sagte, es gibt [keine Notwendigkeit, die db zu schließen] (http://groups.google.com/d/msg/android-developers/NwDRpHUXt0U/jIam4Q8-cqQJ). – bigstones
Dies ist die wichtigste Information zu diesem Thema. Ich habe es zur Antwort gemacht. – philipp