2012-05-04 5 views
3

Я пишу приложение для Android, используя sqlite. Есть много мероприятий и одна услуга. Я использую БД из нескольких потоков. Он отлично работает в Android 2.X, но когда я запускаю его в Android 3.X он всегда выдает эту ошибку и Force Close:Android sqlite with multi thread

05-04 22:17:04.815: I/SqliteDatabaseCpp(8774): sqlite returned: error code = 5, msg = database is locked, db=/data/data/xxx/databases/im 
05-04 22:17:04.815: E/SqliteDatabaseCpp(8774): sqlite3_open_v2("/data/data/xxx/databases/im", &handle, 6, NULL) failed 
05-04 22:17:04.835: E/SQLiteDatabase(8774): Failed to open the database. closing it. 
05-04 22:17:04.835: E/SQLiteDatabase(8774): android.database.sqlite.SQLiteDatabaseLockedException: database is locked 
05-04 22:17:04.835: E/SQLiteDatabase(8774):  at android.database.sqlite.SQLiteDatabase.dbopen(Native Method) 
05-04 22:17:04.835: E/SQLiteDatabase(8774):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983) 
05-04 22:17:04.835: E/SQLiteDatabase(8774):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956) 
05-04 22:17:04.835: E/SQLiteDatabase(8774):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021) 
05-04 22:17:04.835: E/SQLiteDatabase(8774):  at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:790) 
05-04 22:17:04.835: E/SQLiteDatabase(8774):  at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221) 
05-04 22:17:04.835: E/SQLiteDatabase(8774):  at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149) 

Любой знает, почему это происходит и как ее решить?

Я исследовал в Интернете и большинство людей советуют:

  1. Используйте одно соединение с базой данных только для приложения. Как это обеспечить? Я хочу поделиться соединением БД для службы и деятельности. Должен ли я сделать это, создав публичную статическую переменную БД?
  2. ContentProvider - Я использую сложный SQL-запрос в коде (например, объединение нескольких таблиц, временная таблица). Можно ли запустить эту сложную инструкцию SQL в ContentProvider?


    Спасибо всем. Наконец, (1) отлично работает для меня. Но я все еще удивляюсь, почему Android 2.X не имеет этой проблемы.
+0

1) работает только в том случае, если весь доступ происходит с тем же процессом, 2) работает до тех пор, пока все, что вам нужно, это вставка/запрос/обновление/удаление, но сложные запросы выглядят уродливыми, так как вы ограничены разработчиком http: // .android.com/reference/android/content/ContentResolver.html интерфейс – zapl

+0

Благодаря zapl, DB не используется совместно с другими приложениями. Я думаю (1) хорошо для меня. Вы даже не подозреваете, почему Android 2.X не имеет этой проблемы? –

+1

вы должны пойти по этой ссылке http://stackoverflow.com/questions/7930139/android-databse-locked –

ответ

5

Номер 1 является ответом. У меня есть несколько стеков ответы и сообщения в блоге о том, как именно это сделать:

What are the best practices for SQLite on Android?

http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection

Номер 2 много дополнительной работы и ненужной. ContentProvider существует, поэтому вы можете обмениваться данными с другими приложениями. Он используется для управления соединениями с базой данных, потому что люди не понимают, как работают Sqlite и Android.

+0

Thanks Kevin Галлиган, я прочитал ваши сообщения. Я многому научился: http://stackoverflow.com/questions/2493331/what-is-best-practice-with-sqlite-and-android/3689883#3689883. Я пытаюсь решить (1). Я буду изучать ormlite, если решение (1) не выполнено. Спасибо! –

+3

ORMLite хорош, но совершенно не нужен для доступа к базе данных из нескольких потоков. Просто введите статический экземпляр SQLiteOpenHelper или сохраните один экземпляр в Applicatio n. У вас никогда не будет проблем с защитой db, если у вас есть только один экземпляр. –

+0

Спасибо Kevin, ORMLite в любом случае классный –

3

Предлагаю вам использовать ContentProvider с LoaderManager всякий раз, когда вы можете. Он способен автоматически выполнять запросы в фоновом режиме.

+0

Спасибо за совет, но для этого требуется много дополнительных работ, и база данных не будет делиться с другими приложениями. Я думаю, что решение (1) лучше для меня. Я подумаю о вашем предлагаемом решении, если (1) действительно работает.Спасибо –

+2

Я знаю много людей, которые предпочитают ContentProvider, но совершенно не нужны для многопоточного доступа к db. Если вы используете его только для этого, его не нужно. Однако, если вам нравится ContentProvider, используйте его. Однако мне кажется, что это лишняя работа. –