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

SQLite, Preferences, файлы, SD, Content Provider, XML, JSON
Ответить
Аватара пользователя
neoksi
Сообщения: 712
Зарегистрирован: 26 июл 2012, 10:42
Контактная информация:

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

Сообщение neoksi » 19 апр 2013, 09:06

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

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

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

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

Сообщение rezak90 » 19 апр 2013, 09:10

как то наверное не понял вопроса, потому что ответ банальный, close() не?
R.id.team
Политика на форуме запрещена

Аватара пользователя
neoksi
Сообщения: 712
Зарегистрирован: 26 июл 2012, 10:42
Контактная информация:

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

Сообщение neoksi » 19 апр 2013, 09:43

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]

Аватара пользователя
neoksi
Сообщения: 712
Зарегистрирован: 26 июл 2012, 10:42
Контактная информация:

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

Сообщение neoksi » 19 апр 2013, 10:01

Все разобрался, не прибил LoaderManager'ы при разрушении фрагмента. Думал они сами разрушатся =)

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

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

Сообщение Mikhail_dev » 19 апр 2013, 10:06

В гугле я нарыл что проблема в курсоре. Может всё же не в LoaderManager ?

Аватара пользователя
neoksi
Сообщения: 712
Зарегистрирован: 26 июл 2012, 10:42
Контактная информация:

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

Сообщение neoksi » 19 апр 2013, 10:29

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]

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

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

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

Сообщение Mikhail_dev » 19 апр 2013, 10:55

Так вроде при запросе возвращается явный курсор. Их и закрывать. Хотя может тут дело в каких-то неявных курсорах. Точно не знаю.

Аватара пользователя
neoksi
Сообщения: 712
Зарегистрирован: 26 июл 2012, 10:42
Контактная информация:

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

Сообщение neoksi » 19 апр 2013, 11:42

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

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

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

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

Сообщение Foenix » 19 апр 2013, 15:57

странно, У меня при использовании по-старинке managedQuery те же ошибки иной раз вылетают (когда я не закрою или закрою то, что не нужно было закрывать), я лично посчитала, что это все из-за managedQuery, и нужно переделываться на LoaderManager и тогда все это уйдет, оно ведь само долждно следить за одиночными подключениями к бд.. я почему-то думала что дело именно в этом..
теперо думаю стоит ли переделывать или пока не надо..
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
neoksi
Сообщения: 712
Зарегистрирован: 26 июл 2012, 10:42
Контактная информация:

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

Сообщение neoksi » 19 апр 2013, 22:42

Стоит, но нужно следить за их уничтожением.

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

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

Сообщение Foenix » 19 апр 2013, 23:46

да переделаю, конечно. Ты так быстро, кстати, переделал. не накидаешь где-нибудь принципиальные пункты как побыстрее перейти? :)
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
neoksi
Сообщения: 712
Зарегистрирован: 26 июл 2012, 10:42
Контактная информация:

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

Сообщение neoksi » 20 апр 2013, 02:32

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

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

Ответить