AsyncQueryHandler 批量插入
AsyncQueryHandler bulk insert
我想 运行 在后台线程中执行我的 Content Resolver 操作(查询、插入、删除)。
我发现 AsyncQueryHandler 可以解决我的问题。 AsyncQueryHandler 的问题是:批量插入。我的应用程序中有这种操作,并且在 AsyncQueryHandler class 中没有要覆盖的 bulkInsert 方法。
在处理 AsyncQueryHandler 时如何处理批量插入?除了 AsyncQueryHandler 之外还有其他选择吗?
嘿,您可以在这种情况下使用 CursorLoader。这将查询内容解析器和 returns 游标。它使用 AsyncTaskLoader 在后台线程上执行游标查询,这样它就不会阻塞应用程序的 UI。
您可以查看 http://www.theappguruz.com/blog/use-android-cursorloader-example 了解更多详情。
并且您可以像下面这样将批量插入方法定义到您的内容提供程序中
@Override
public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
//mOpenHelper is object of helper class.
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
db.beginTransaction();
int rowsInserted = 0;
try {
for (ContentValues value : values) {
long _id = db.insert(TABLE_NAME, null, value);
if (_id != -1) {
rowsInserted++;
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
if (rowsInserted > 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return rowsInserted;
}
最后,我改变了我的架构。
我删除了 bulkInsert 并对内容值数组进行了交互。这样我就可以毫无问题地使用 AsyncQueryHandler。
想来想去,我认为这是我最好的选择。
AsyncQueryHandler
不支持 bulkInsert
可能是因为此方法不保证插入的原子性。这是什么意思?好吧,如果 startInsert
由于某种原因失败,则没有完成任何插入。这意味着您可以不进行任何插入,也可以进行一次插入。只有2个选项。保持原子性,即,如果失败,底层数据源保持与以前相同。
如果 10 项中的 bulkInsert
由于某种原因在中间失败,可以有多种选择:插入 3 项或插入 5 项。因此没有原子性。当 ContentProvider
没有覆盖 bulkInsert
并最终多次使用隐式 insert
时,就会发生这种情况。因此,在插入每个项目后,事务被认为是成功的并进行了提交。这意味着对于 10 个项目,发生 10 个事务,如果其中任何一个失败,则不会回滚到数据源的先前状态。操作的原子性丢失。
但这很糟糕。如果您拥有 ContentProvider
并且您已覆盖 bulkInsert
并确保保持原子性怎么办。那么你应该可以使用AsyncQueryHandler
来执行bulkInsert
。 https://github.com/Madrapps/AsyncQuery 库正是这样做的。它与 Android 的 AsyncQueryHandler
相同,但支持 bulkInsert
。
如果您担心原子性,请确保您使用自己的 ContentProvider
可以处理 bulkInsert
。
我想 运行 在后台线程中执行我的 Content Resolver 操作(查询、插入、删除)。
我发现 AsyncQueryHandler 可以解决我的问题。 AsyncQueryHandler 的问题是:批量插入。我的应用程序中有这种操作,并且在 AsyncQueryHandler class 中没有要覆盖的 bulkInsert 方法。
在处理 AsyncQueryHandler 时如何处理批量插入?除了 AsyncQueryHandler 之外还有其他选择吗?
嘿,您可以在这种情况下使用 CursorLoader。这将查询内容解析器和 returns 游标。它使用 AsyncTaskLoader 在后台线程上执行游标查询,这样它就不会阻塞应用程序的 UI。 您可以查看 http://www.theappguruz.com/blog/use-android-cursorloader-example 了解更多详情。
并且您可以像下面这样将批量插入方法定义到您的内容提供程序中
@Override
public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
//mOpenHelper is object of helper class.
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
db.beginTransaction();
int rowsInserted = 0;
try {
for (ContentValues value : values) {
long _id = db.insert(TABLE_NAME, null, value);
if (_id != -1) {
rowsInserted++;
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
if (rowsInserted > 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return rowsInserted;
}
最后,我改变了我的架构。
我删除了 bulkInsert 并对内容值数组进行了交互。这样我就可以毫无问题地使用 AsyncQueryHandler。
想来想去,我认为这是我最好的选择。
AsyncQueryHandler
不支持 bulkInsert
可能是因为此方法不保证插入的原子性。这是什么意思?好吧,如果 startInsert
由于某种原因失败,则没有完成任何插入。这意味着您可以不进行任何插入,也可以进行一次插入。只有2个选项。保持原子性,即,如果失败,底层数据源保持与以前相同。
如果 10 项中的 bulkInsert
由于某种原因在中间失败,可以有多种选择:插入 3 项或插入 5 项。因此没有原子性。当 ContentProvider
没有覆盖 bulkInsert
并最终多次使用隐式 insert
时,就会发生这种情况。因此,在插入每个项目后,事务被认为是成功的并进行了提交。这意味着对于 10 个项目,发生 10 个事务,如果其中任何一个失败,则不会回滚到数据源的先前状态。操作的原子性丢失。
但这很糟糕。如果您拥有 ContentProvider
并且您已覆盖 bulkInsert
并确保保持原子性怎么办。那么你应该可以使用AsyncQueryHandler
来执行bulkInsert
。 https://github.com/Madrapps/AsyncQuery 库正是这样做的。它与 Android 的 AsyncQueryHandler
相同,但支持 bulkInsert
。
如果您担心原子性,请确保您使用自己的 ContentProvider
可以处理 bulkInsert
。