Sqlite транзакция блокирует Android UI - PullRequest
4 голосов
/ 25 октября 2011

В моем приложении для Android работает AsyncTask, который работает довольно долго, чтобы обновить базу данных при запуске приложения. Мне нужно обернуть это в транзакции, чтобы откатить вещи, если пользователь выходит из приложения до завершения задачи. Однако, поскольку обертывание кода в транзакции блокирует пользовательский интерфейс, пока задача не будет завершена. Почему это так, поскольку код уже выполняется в отдельном потоке?

Я использую ORMLite, и это, в основном, оболочка для транзакции, код для обновления БД идет внутрь call () .., до добавления кода для обновления БД внутри транзакции не было блокировки пользовательского интерфейса. ...

public ConnectionSource source; 
@Override
protected Boolean doInBackground(Context... params) {
    try {
        TransactionManager.callInTransaction(source, new Callable<Void>() {
            public Void call() throws Exception {
                return null;
            }
        });

Ответы [ 2 ]

7 голосов
/ 25 октября 2011

К сожалению, транзакции SQLite являются эксклюзивными и блокируют все остальные операции с базой данных.Я подозреваю, что даже если вы находитесь в другом потоке, поток пользовательского интерфейса выполняет какие-то действия с базой данных, которые должны ждать завершения транзакции.

0 голосов
/ 03 октября 2016

Поскольку API 11 Android допускает одну записывающую нить и множество читающих нитей в режиме WAL. Вы должны переключиться в режим WAL и использовать beginTransactionNonExclusive (), чтобы избежать блокировки потоков чтения.

int flags = SQLiteDatabase.CREATE_IF_NECESSARY;
if(walModeEnabled) {
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
       flags = flags | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;
   }
}

SQLiteDatabase db = SQLiteDatabase.openDatabase(databasePath.getPath(), null, flags);

// backward compatibility hack to support WAL on pre-jelly-bean devices
if(walModeEnabled) {
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB &&
           Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
       db.enableWriteAheadLogging();
   } else {
       Log.w(TAG, "WAL is not supported on API levels below 11.");
   }
}

Проверьте мою статью для более подробной информации о режиме WAL и конкуренции в SQLite:

http://www.skoumal.net/en/parallel-read-and-write-in-sqlite/

...