@jcwenger 首先,在阅读了您的帖子后,我认为bulkInsert比ApplyBatch更快是因为这个原因,但在阅读了联系人提供程序的代码后,我不这么认为。
1.您说ApplyBatch使用事务,是的,但bulkInsert也使用事务。以下是它的代码:
public int bulkInsert(Uri uri, ContentValues[] values) {
int numValues = values.length;
mDb = mOpenHelper.getWritableDatabase();
mDb.beginTransactionWithListener(this);
try {
for (int i = 0; i < numValues; i++) {
Uri result = insertInTransaction(uri, values[i]);
if (result != null) {
mNotifyChange = true;
}
mDb.yieldIfContendedSafely();
}
mDb.setTransactionSuccessful();
} finally {
mDb.endTransaction();
}
onEndTransaction();
return numValues;
}
也就是说,bulkInsert 也使用事务。所以我不认为这是原因。
2.你说 bulkInsert 将一堆值应用于同一个表中。很抱歉,我在 froyo 的源代码中找不到相关的代码。我想知道你是如何找到的?你能告诉我吗?
我认为原因是:
bulkInsert 使用 mDb.yieldIfContendedSafely(),而 applyBatch 使用 mDb.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY)/*SLEEP_AFTER_YIELD_DELAY = 4000*/。
阅读 SQLiteDatabase.java 的代码后,我发现,如果在 yieldIfContendedSafely 中设置了时间,它将会休眠,但如果没有设置时间,它将不会休眠。你可以参考下面的代码片段:
private boolean yieldIfContendedHelper(boolean checkFullyYielded, long sleepAfterYieldDelay) {
if (mLock.getQueueLength() == 0) {
mLockAcquiredWallTime = SystemClock.elapsedRealtime();
mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
return false;
}
setTransactionSuccessful();
SQLiteTransactionListener transactionListener = mTransactionListener;
endTransaction();
if (checkFullyYielded) {
if (this.isDbLockedByCurrentThread()) {
throw new IllegalStateException(
"Db locked more than once. yielfIfContended cannot yield");
}
}
if (sleepAfterYieldDelay > 0) {
long remainingDelay = sleepAfterYieldDelay;
while (remainingDelay > 0) {
try {
Thread.sleep(remainingDelay < SLEEP_AFTER_YIELD_QUANTUM ?
remainingDelay : SLEEP_AFTER_YIELD_QUANTUM);
} catch (InterruptedException e) {
Thread.interrupted();
}
remainingDelay -= SLEEP_AFTER_YIELD_QUANTUM;
if (mLock.getQueueLength() == 0) {
break;
}
}
}
beginTransactionWithListener(transactionListener);
return true;
}
我认为这就是bulkInsert比applyBatch更快的原因。
如有任何问题,请与我联系。