5

私のAndroidアプリには、アプリの起動時にデータベースを更新するために実行している比較的長時間実行されるAsyncTaskがあります。タスクが完了する前にユーザーがアプリを終了した場合にロールバックするために、それをトランザクションでラップする必要があります。ただし、コードをトランザクションにラップするため、タスクが完了するまでUIがブロックされます。コードが既に別のスレッドで実行されているため、これはなぜでしょうか?

私は ORMLite を使用していますが、これは基本的にトランザクションのラッパーです。db を更新するコードは call().. 内に入ります。トランザクション内で db を更新するコードを追加する前に、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 モードで 1 つの書き込みスレッドと多数の読み取りスレッドが許可されます。読み取りスレッドのブロックを回避するには、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 に答える