Функция SQLiteDatabase close (), вызывающая исключение NullPointerException при нескольких потоках - PullRequest
5 голосов
/ 03 ноября 2011

Я обнаружил в своем проекте, что функция close () в реализации SQLiteDatabase на Android выдает исключение NullPointerException при запуске нескольких потоков, которые открывают базу данных, вставляют данные, а затем закрывают базу данных.Все работает гладко, если я не позволю каждому потоку закрываться () после вставки в базу данных.

Вот пример того, как может выглядеть один из потоков записи

        ContentValues values = new ContentValues();
        values.put(CallDetailsStorageConstants.COLUMN_NAME_REMOTE_NAME_IDX, (String) "");
        values.put(CallDetailsStorageConstants.COLUMN_NAME_REMOTE_MEETINGID_IDX, (String) "");

        CalculonDatabase callDetailsOpenHelper = CalculonDatabase.getInstance(mContext);
        SQLiteDatabase dbw = callDetailsOpenHelper.getWritableDatabase();

        long rowid = 0;
        try {
            rowid = dbw.insertWithOnConflict(CallDetailsTable.CALL_DETAILS_TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
        } catch (SQLiteConstraintException e) {
            e.printStackTrace();
        } finally {
            dbw.close();
        }

.что в конце делается вызов close ().При запуске нескольких потоков я получаю это исключение.

11-03 03:39:26.128: E/AndroidRuntime(977): FATAL EXCEPTION: Thread-17
11-03 03:39:26.128: E/AndroidRuntime(977): java.lang.NullPointerException
11-03 03:39:26.128: E/AndroidRuntime(977):  at     android.database.sqlite.SQLiteStatement.releaseAndUnlock(SQLiteStatement.java:283)
11-03 03:39:26.128: E/AndroidRuntime(977):  at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:96)
11-03 03:39:26.128: E/AndroidRuntime(977):  at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1933)
11-03 03:39:26.128: E/AndroidRuntime(977):  at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1864)
11-03 03:39:26.128: E/AndroidRuntime(977):  at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:636)
11-03 03:39:26.128: E/AndroidRuntime(977):  at android.database.sqlite.SQLiteDatabase.beginTransactionNonExclusive(SQLiteDatabase.java:551)
11-03 03:39:26.128: E/AndroidRuntime(977):  at android.database.sqlite.SQLiteStatement.acquireAndLock(SQLiteStatement.java:240)
11-03 03:39:26.128: E/AndroidRuntime(977):  at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:111)
11-03 03:39:26.128: E/AndroidRuntime(977):  at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1737)
11-03 03:39:26.128: E/AndroidRuntime(977):  at com.smash.DBWritingThread.run(DBWritingThread.java:50)

Мой вопрос: почему эта ошибка возникает только при использовании функции close ()?Кроме того, можно ли использовать close () намного позже или, возможно, никогда?

Любые советы по этой проблеме очень приветствуются.

Ответы [ 4 ]

13 голосов
/ 03 ноября 2011

У меня есть ваши ответы!

Никогда не закрывайте БД. Это так просто.

Убедитесь, что у вас есть только один, повторите, * один экземпляр помощника на приложение. Поделитесь этим со всеми темами.

http://www.touchlab.co/blog/single-sqlite-connection/

Вот еще немного информации о внутренностях sqlite и блокировке:

http://www.touchlab.co/blog/android-sqlite-locking/

4 голосов
/ 03 ноября 2011

Тебе не нужно беспокоиться.См. это обсуждение , которое включает подтверждение того, что закрытие базы данных выполняется системой по мере необходимости, если / когда процесс завершается.

Соответствующая цитата от сотрудника Google:

Поставщик контента создается при создании процесса хостинга и остается в нем в течение всего процесса, , поэтому нет необходимости закрывать базу данных - он будетбыть закрытым как часть ядра, очищающего ресурсы процесса, когда процесс убит.

1 голос
/ 03 ноября 2011

Если вы работаете непосредственно с базой данных SQLite, не обращаясь к провайдеру контента, я видел шаблон, который использовался для закрытия базы данных в Application.onTerminate, тогда как экземпляр Application хранит «адаптер» одноэлементной базы данных, которыйбудет объект, содержащий SQLiteDatabase и его SQLiteOpenHelper.

0 голосов
/ 13 июля 2012

Похоже на эту проблему: функция SQLiteDatabase close (), вызывающая исключение NullPointerException при нескольких потоках

Возможно, вам не нужно вызывать database.close ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...