我已经在SQLite数据库上使用了applyBatch进行插入,更新和删除操作,首次安装app和定期同步的条目超过2000个,由于数据库应用程序上的大量操作得到停止响应。 applyBatch大约需要30-40秒才能完成。
我见过解决方案 来自Insertion of thousands of contact entries using applyBatch is slow的ContentResolver.bulkInsert(Uri url,ContentValues []值)
但它仅用于插入操作,我有查询插入,更新和删除的组合。
我也尝试使用AsyncTask
private class InsertTask extends AsyncTask<ArrayList<ContentProviderOperation>, Integer, Void> {
@Override
protected Void doInBackground(ArrayList<ContentProviderOperation>... params) {
try {
providerClient.applyBatch(params[0]);
} catch (RemoteException e) {
e.printStackTrace();
} catch (OperationApplicationException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
谢谢。
答案 0 :(得分:2)
申请批次
通常,批处理作业将在一个跨越所有操作的事务中执行。但是如果你的工作包含很多操作,那么事务可能会持续很长时间,并且可能阻止其他任务被执行。
使用批量操作的另一面是大批量可能 长时间锁定数据库阻止其他应用程序 从访问数据和可能导致ANR(“应用程序不 回应“对话框。”
为避免数据库的此类锁定,请确保在批次中插入“屈服点”。
屈服点:
产量点向内容提供者指示在执行下一个操作之前,它可以提交已经进行的更改,产生其他请求,打开另一个事务并继续处理操作。屈服点不会自动提交事务,但只有在数据库上有另一个请求时才会提交。
因此,您应该在开头设置 withYieldAllowed() 每个业务块。
希望它会对你有帮助!
答案 1 :(得分:0)
这里我回复了我自己的问题,问题是由于每个条目在同一个网址上的许多notifyChange()请求,我使用下面的代码推迟了通知
首先覆盖applyBatch函数
private boolean applyingBatch = false;
private List<Uri> delayedNotifications;
@NonNull
@Override
public ContentProviderResult[] applyBatch(@NonNull ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {
final SQLiteDatabase db = dbHelper.getWritableDatabase();
db.beginTransaction();
try {
applyingBatch = true;
final int numOperations = operations.size();
final ContentProviderResult[] results = new ContentProviderResult[numOperations];
for (int i = 0; i < numOperations; i++) {
results[i] = operations.get(i).apply(this, results, i);
}
db.setTransactionSuccessful();
applyingBatch = false;
/*
*
* Notify to all URL where change it made
* */
synchronized (delayedNotifications) {
for (Uri uri : delayedNotifications) {
getContext().getContentResolver().notifyChange(uri, null);
}
}
return results;
} finally {
applyingBatch = false;
db.endTransaction();
}
}
然后检查批处理操作进度是否存储延迟通知,否则发送通知
protected void sendNotification(Uri uri) {
if (applyingBatch) {
if (delayedNotifications == null) {
delayedNotifications = new ArrayList<Uri>();
}
synchronized (delayedNotifications) {
if (!delayedNotifications.contains(uri)) {
delayedNotifications.add(uri);
LogUtil.debug("ProcessExeCheck added " + uri);
}
}
} else {
getContext().getContentResolver().notifyChange(uri, null);
}
}
检查插入,更新和删除的通知
@Override
public Uri insert(Uri uri, ContentValues values) {
Uri result;
long rawId;
switch (URI_MATCHER.match(uri)) {
case ALL_LIST:
rawId = dbHelper.getWritableDatabase().insert(Table.TABLE_NAME, null, values);
result = Station.getUriById(rawId);
default:
throw new IllegalArgumentException("Uri " + uri + " is not supported");
}
sendNotification(LIST.CONTENT_URI);
return result;
}