5

在我的 android 应用程序中,有一个运行时间相对较长的 AsyncTask 我正在运行以在应用程序启动时更新数据库。如果用户在任务完成之前退出应用程序,我需要将其包装在事务中以回滚。但是,由于将代码包装在事务中,它会阻塞用户界面,直到任务完成。为什么会这样,因为代码已经在单独的线程中运行?

我正在使用ORMLite,这基本上是事务的包装器,更新数据库的代码进入call()..,在添加代码以更新事务中的数据库之前,没有锁定ui ...

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

2 回答 2

7

不幸的是,SQLite 事务是独占的,它们会阻止所有其他数据库活动。我怀疑即使您在另一个线程中,UI 线程也在执行某种数据库活动,必须等待事务完成。

于 2011-10-25T17:00:51.890 回答
0

由于 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.");
   }
}

查看我的文章以获取有关 SQLite 中 WAL 模式和并发性的更多详细信息:

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

于 2016-10-03T10:34:11.553 回答