Lor*_*ori 11 sqlite android cursor android-contentprovider android-cursoradapter
我有一个自定义ContentProvider
管理SQLite数据库的访问.要在a中加载数据库表的内容ListFragment
,我使用LoaderManager
with a CursorLoader
和a 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);
}
}
Run Code Online (Sandbox Code Playgroud)
SQLite数据库由后台任务更新,后台任务从Web服务获取大量项目,并通过ContentProvider
批处理操作将这些项目插入数据库(ContentResolver#applyBatch()
).
即使这是批处理操作,ContentProvider#insert()
也会将每个调用的每一行调用插入到数据库中,并在当前实现中ContentProvider
调用setNotificationUri()
每个插入命令.
结果是CursorAdapter
接收到通知突发,导致UI过于频繁地更新,从而产生恼人的闪烁效果.
理想情况下,当批处理操作正在进行时,应该有一种方法ContentObserver
只在任何批处理操作结束时通知,而不是每个插入命令.
有人知道这是否可行?请注意我可以更改ContentProvider
实现并覆盖其任何方法.
Dia*_*rat 13
我发现了一个比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();
}
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个确切的问题,我重写了applyBatch并设置了一个阻止其他方法发送通知的标志.
volatile boolean applyingBatch=false;
public ContentProviderResult[] applyBatch(
ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
applyingBatch=true;
ContentProviderResult[] result;
try {
result = super.applyBatch(operations);
} catch (OperationApplicationException e) {
throw e;
}
applyingBatch=false;
synchronized (delayedNotifications) {
for (Uri uri : delayedNotifications) {
getContext().getContentResolver().notifyChange(uri, null);
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
我公开了一种方法来"存储"批处理完成时要发送的通知:
protected void sendNotification(Uri uri) {
if (applyingBatch) {
if (delayedNotifications==null) {
delayedNotifications=new ArrayList<Uri>();
}
synchronized (delayedNotifications) {
if (!delayedNotifications.contains(uri)) {
delayedNotifications.add(uri);
}
}
} else {
getContext().getContentResolver().notifyChange(uri, null);
}
}
Run Code Online (Sandbox Code Playgroud)
任何发送通知的方法都使用sendNotification,而不是直接触发通知.
可能有更好的方法来做到这一点 - 它看起来似乎应该是 - 但这就是我所做的.
归档时间: |
|
查看次数: |
4080 次 |
最近记录: |