我有一个自定义图库应用,可以将图像数据存储在数据库中。该图库是由GridView
支持的CursorAdapter
。
首次请求图像解码时ContentResolver.update
更新后台线程中的高度,宽度和方向。由于许多图像一次可见,因此当用户滚动时数据库更新会快速发生,这会导致支持CursorLoader
快速刷新GridView
,这表现为快速闪烁。
如果底层来源可以快速更改,或者我在这里遗漏了什么,是否无法使用CursorLoader
和CursorAdapter
?
答案 0 :(得分:0)
当数据库中的监控数据(选择,投影)发生变化时,LoaderManager
只会提供一个新光标。因此,就CursorAdapter
而言,每次更新数据库时都会有一个全新的数据源(swapCursor
):
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor)
{
mGalleryAdapter.swapCursor(cursor);
}
因此,附加到动态CursorAdapter
的理想LoaderManager
将需要微观管理视图更新,以确保它不会更新完全相同的视图。为此(因为我的观点相当复杂),我创建了一个辅助对象来处理光标和视图之间的转换和比较(为了简洁起见,删除了大多数视图)。
public static class GalleryItem
{
private String name;
private int rotation;
public static GalleryItem fromCursor(Context c, Cursor cursor)
{
GalleryItem item = new GalleryItem();
item.rotation = ImageUtils.getRotation(cursor.getInt(Meta.ORIENTATION_COLUMN));
item.name = cursor.getString(Meta.NAME_COLUMN);
return item;
}
public static GalleryItem fromViewHolder(ViewHolder vh)
{
GalleryItem item = new GalleryItem();
item.rotation = (int)vh.mImageView.getRotation();
item.name = (String) vh.mFileName.getText();
return item;
}
@Override
public boolean equals(Object o)
{
GalleryItem compare = (GalleryItem) o;
boolean sameRotation = rotation == compare.rotation;
boolean sameName = name == null ? compare.name == null : name.equals(compare.name);
return sameName && sameRotation;
}
}
然后使用它来检查您是否需要更新视图中的任何内容:
@Override
public void onBindViewHolder(ViewHolder vh, final int position, Cursor cursor)
{
GalleryItem galleryItem = GalleryItem.fromCursor(mContext, cursor);
GalleryItem former = GalleryItem.fromViewHolder(vh);
// If nothing has changed avoid refreshing.
// The reason for this is that loaderManagers replace cursors meaning every change
// will refresh the entire data source causing flickering
if (former.equals(galleryItem))
return;
...
长话短说,动态LoaderManager
你必须实现一种方法来跳过重新创建完全不变的视图。