我有一个自定义的ContentProvider
,用于管理对SQLite数据库的访问。要将数据库表的内容加载到ListFragment
中,我将LoaderManager
与CursorLoader
和CursorAdapter
结合使用:
public class MyListFragment extends ListFragment implements LoaderCallbacks<Cursor> {
// ...
CursorAdapter mAdapter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new CursorAdapter(getActivity(), null, 0);
setListAdapter(mAdapter);
getLoaderManager().initLoader(LOADER_ID, null, this);
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), CONTENT_URI, PROJECTION, null, null, null);
}
public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
mAdapter.swapCursor(c);
}
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
}
SQLite数据库通过后台任务进行更新,该后台任务从Web服务中获取许多项,并通过
ContentProvider
批处理操作(ContentResolver#applyBatch()
)将这些项插入数据库中。即使这是一个批处理操作,也会将每行的
ContentProvider#insert()
插入数据库中,并且在当前实现中,ContentProvider
会为每个insert命令调用setNotificationUri()
。结果是
CursorAdapter
接收到突发通知,从而导致UI过于频繁地更新,从而产生令人讨厌的闪烁效果。理想情况下,当正在进行批处理操作时,应该有一种方法仅在任何批处理操作结束时通知
ContentObserver
,而不是与每个插入命令一起通知。有人知道这是否可能吗?请注意,我可以更改
ContentProvider
实现并覆盖其任何方法。 最佳答案
我找到了一个更简单的解决方案,该解决方案是我从Google的I/O应用程序中发现的。您只需要重写ContentProvider中的applyBatch方法并执行事务中的所有操作即可。直到事务提交,才发送通知,这将减少发出的ContentProvider更改通知的数量:
@Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
final SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.beginTransaction();
try {
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();
return results;
} finally {
db.endTransaction();
}
}
关于当使用批处理操作插入许多行时,Android ContentProvider会向CursorAdapter调用setNotificationUri()突发,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9801304/