Страница 1 из 1

Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 09:06
neoksi
В контент провайдере у меня меняется открытая БД в SQLiteOpenHelper в зависимости от выбранного профиля пользователя.

Возник следующий вопрос, как правильно закрыть текущую копию SQLiteOpenHelper, чтоб прибить все ссылки на неё, перед тем как создавать следующую?

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 09:10
rezak90
как то наверное не понял вопроса, потому что ответ банальный, close() не?

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 09:43
neoksi
rezak90 писал(а):как то наверное не понял вопроса, потому что ответ банальный, close() не?
Я тоже так думал, но появляются разные ошибки, при разных вариациях.

Я думаю все из-за того, что что в методе query контент провайдера мы вешаем на раздаваемые курсоры наблюдатели за определенными Uri:
[syntax=java]c.setNotificationUri(getContext().getContentResolver(), uri);[/syntax]
И в результате при перезапросе этих курсоров, вылезает всякая бяка =)

Я вот думаю, как эту нотификацию сбросить...

Я вот делаю хелперу Close(), а в логах вижу следующее:
[syntax=xml]04-19 10:34:53.970: E/Database(15842): close() was never explicitly called on database '/data/data/timeact.app.pro/databases/*****.20537.***'
04-19 10:34:53.970: E/Database(15842): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
04-19 10:34:53.970: E/Database(15842): at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1847)
04-19 10:34:53.970: E/Database(15842): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:820)
04-19 10:34:53.970: E/Database(15842): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:854)
04-19 10:34:53.970: E/Database(15842): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:847)
04-19 10:34:53.970: E/Database(15842): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:547)
04-19 10:34:53.970: E/Database(15842): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
04-19 10:34:53.970: E/Database(15842): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:118)
04-19 10:34:53.970: E/Database(15842): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
04-19 10:34:53.970: E/Database(15842): at timeact.app.pro.provider.ContentProviderData.query(ContentProviderData.java:308)
04-19 10:34:53.970: E/Database(15842): at android.content.ContentProvider$Transport.query(ContentProvider.java:190)
04-19 10:34:53.970: E/Database(15842): at android.content.ContentResolver.query(ContentResolver.java:262)
04-19 10:34:53.970: E/Database(15842): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:49)
04-19 10:34:53.970: E/Database(15842): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:35)
04-19 10:34:53.970: E/Database(15842): at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240)
04-19 10:34:53.970: E/Database(15842): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51)
04-19 10:34:53.970: E/Database(15842): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40)
04-19 10:34:53.970: E/Database(15842): at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123)
04-19 10:34:53.970: E/Database(15842): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
04-19 10:34:53.970: E/Database(15842): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
04-19 10:34:53.970: E/Database(15842): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
04-19 10:34:53.970: E/Database(15842): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
04-19 10:34:53.970: E/Database(15842): at java.lang.Thread.run(Thread.java:1019)
[/syntax]

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 10:01
neoksi
Все разобрался, не прибил LoaderManager'ы при разрушении фрагмента. Думал они сами разрушатся =)

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 10:06
Mikhail_dev
В гугле я нарыл что проблема в курсоре. Может всё же не в LoaderManager ?

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 10:29
neoksi
no-- писал(а):В гугле я нарыл что проблема в курсоре. Может всё же не в LoaderManager ?
Ну да, ошибка повторилась, после внесения изменений, но лог уже другой:
[syntax=xml]04-19 11:19:03.630: E/Cursor(16476): Invalid statement in fillWindow()
04-19 11:19:03.670: E/Cursor(16476): Invalid statement in fillWindow()
04-19 11:19:03.760: E/AndroidRuntime(16476): FATAL EXCEPTION: ModernAsyncTask #2
04-19 11:19:03.760: E/AndroidRuntime(16476): java.lang.RuntimeException: An error occured while executing doInBackground()
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:137)
04-19 11:19:03.760: E/AndroidRuntime(16476): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
04-19 11:19:03.760: E/AndroidRuntime(16476): at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
04-19 11:19:03.760: E/AndroidRuntime(16476): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
04-19 11:19:03.760: E/AndroidRuntime(16476): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
04-19 11:19:03.760: E/AndroidRuntime(16476): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
04-19 11:19:03.760: E/AndroidRuntime(16476): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
04-19 11:19:03.760: E/AndroidRuntime(16476): at java.lang.Thread.run(Thread.java:1019)
04-19 11:19:03.760: E/AndroidRuntime(16476): Caused by: java.lang.IllegalStateException: database not open
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1343)
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:330)
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:280)
04-19 11:19:03.760: E/AndroidRuntime(16476): at timeact.app.pro.provider.ContentProviderData.query(ContentProviderData.java:310)
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.content.ContentProvider$Transport.query(ContentProvider.java:190)
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.content.ContentResolver.query(ContentResolver.java:262)
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:49)
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:35)
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240)
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51)
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40)
04-19 11:19:03.760: E/AndroidRuntime(16476): at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123)
04-19 11:19:03.760: E/AndroidRuntime(16476): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
04-19 11:19:03.760: E/AndroidRuntime(16476): ... 4 more
[/syntax]

А еще и вот так вот:
[syntax=xml]04-19 11:27:38.025: E/Cursor(16862): Invalid statement in fillWindow()
04-19 11:27:38.165: E/Database(16862): sqlite3_exec to set journal_mode = WAL failed
04-19 11:27:38.165: E/Cursor(16862): Invalid statement in fillWindow()
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): Couldn't open ********.864.*** for writing (will try read-only):
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): android.database.sqlite.SQLiteException: database is locked
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1849)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:820)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:854)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:847)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:547)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:118)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at timeact.app.pro.provider.ContentProviderData.query(ContentProviderData.java:308)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.content.ContentProvider$Transport.query(ContentProvider.java:190)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.content.ContentResolver.query(ContentResolver.java:262)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:49)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:35)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
04-19 11:27:38.185: E/SQLiteOpenHelper(16862): at java.lang.Thread.run(Thread.java:1019)
04-19 11:27:38.195: E/Cursor(16862): Invalid statement in fillWindow()
04-19 11:27:38.215: E/Database(16862): sqlite3_close(0x49fb60) failed: 5
04-19 11:27:38.225: E/Cursor(16862): Invalid statement in fillWindow()
04-19 11:27:38.265: E/AndroidRuntime(16862): FATAL EXCEPTION: ModernAsyncTask #3
04-19 11:27:38.265: E/AndroidRuntime(16862): java.lang.RuntimeException: An error occured while executing doInBackground()
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:137)
04-19 11:27:38.265: E/AndroidRuntime(16862): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
04-19 11:27:38.265: E/AndroidRuntime(16862): at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
04-19 11:27:38.265: E/AndroidRuntime(16862): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
04-19 11:27:38.265: E/AndroidRuntime(16862): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
04-19 11:27:38.265: E/AndroidRuntime(16862): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
04-19 11:27:38.265: E/AndroidRuntime(16862): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
04-19 11:27:38.265: E/AndroidRuntime(16862): at java.lang.Thread.run(Thread.java:1019)
04-19 11:27:38.265: E/AndroidRuntime(16862): Caused by: android.database.sqlite.SQLiteException: unable to close due to unfinalised statements
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.database.sqlite.SQLiteDatabase.dbclose(Native Method)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.database.sqlite.SQLiteDatabase.onAllReferencesReleased(SQLiteDatabase.java:323)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.database.sqlite.SQLiteDatabase.close(SQLiteDatabase.java:884)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.database.sqlite.SQLiteOpenHelper.close(SQLiteOpenHelper.java:220)
04-19 11:27:38.265: E/AndroidRuntime(16862): at timeact.app.pro.provider.ContentProviderData.checkOpenDB(ContentProviderData.java:86)
04-19 11:27:38.265: E/AndroidRuntime(16862): at timeact.app.pro.provider.ContentProviderData.query(ContentProviderData.java:272)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.content.ContentProvider$Transport.query(ContentProvider.java:190)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.content.ContentResolver.query(ContentResolver.java:262)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:49)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:35)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40)
04-19 11:27:38.265: E/AndroidRuntime(16862): at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123)
04-19 11:27:38.265: E/AndroidRuntime(16862): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
04-19 11:27:38.265: E/AndroidRuntime(16862): ... 4 more
04-19 11:27:38.795: E/Database(16862): sqlite3_close(0x49fb60) failed: 5
[/syntax]

Как бы точно закрыть все курсоры ссылающиеся на прошлую базу?

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 10:55
Mikhail_dev
Так вроде при запросе возвращается явный курсор. Их и закрывать. Хотя может тут дело в каких-то неявных курсорах. Точно не знаю.

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 11:42
neoksi
no-- писал(а):Так вроде при запросе возвращается явный курсор. Их и закрывать. Хотя может тут дело в каких-то неявных курсорах. Точно не знаю.
Попробовал я запоминать все выдаваемые курсоры в коллекцию и перед закрытием SQLiteOpenHelper проходиться и закрывать все открытые курсоры, вызвало только дополнительные ошибки.

Вроде оптимизировал все до такой степени, что чтоб вызвать такую ошибку, нужно со скоростью метеора переключаться между учетными записями, врятли пользователям удастся так разогнаться, а иначе она теперь вообще не вылезает ;)

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 15:57
Foenix
странно, У меня при использовании по-старинке managedQuery те же ошибки иной раз вылетают (когда я не закрою или закрою то, что не нужно было закрывать), я лично посчитала, что это все из-за managedQuery, и нужно переделываться на LoaderManager и тогда все это уйдет, оно ведь само долждно следить за одиночными подключениями к бд.. я почему-то думала что дело именно в этом..
теперо думаю стоит ли переделывать или пока не надо..

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 22:42
neoksi
Стоит, но нужно следить за их уничтожением.

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 19 апр 2013, 23:46
Foenix
да переделаю, конечно. Ты так быстро, кстати, переделал. не накидаешь где-нибудь принципиальные пункты как побыстрее перейти? :)

Re: Как правильно закрыть SQLiteOpenHelper

Добавлено: 20 апр 2013, 02:32
neoksi
Olivka писал(а):да переделаю, конечно. Ты так быстро, кстати, переделал. не накидаешь где-нибудь принципиальные пункты как побыстрее перейти? :)
Мне просто повезло, я вручную обсерверы на курсоры вешал для обработки, а тут все тоже самое, только теперь самому не нужно обсерверы на курсоры вешать, это делает ЛоадМенеджер.

П.С. может чуть позже и напишу.