Jus*_*ips 25 android listview asynchronous image
我用Google搜索了这个,但找不到答案,所以这里......
我有一个ListView,显示一些文本和图像.底层适配器出于性能原因(根据推荐的方法)回收视图,并且我根据Android开发者网站的位图页面上的建议使用AsynchTask加载图像.
一切都很顺利,但我有一个问题.当适配器中的视图被回收时,它仍然具有对旧图像(ImageView)的引用.如果用户缓慢滚动,则AsynchTask有足够的时间加载新图像并显示它,因此没有可见的新图像重新加载到用户.
但是,如果用户非常快速地滚动,则加载图像的延迟意味着他们在被新图像替换之前看到旧图像(当View被另一个项目使用时加载).
所以,我的问题是,如何检测屏幕上何时不再显示视图,以便我可以删除图像?这将意味着用户看到一个空的列表视图项,最终将加载适当的图像,这看起来会更好.
提前谢谢了.这是列表视图适配器代码.
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
ListViewHolder viewHolder;
// if this is not a recycled view then create a new view for the data...
if (view == null)
{
view = this.inflater.inflate(R.layout.target_list_view_layout, null, true);
viewHolder = new ListViewHolder();
viewHolder.manufacturer = (TextView) view.findViewById(R.id.manufacturer);
viewHolder.targetName = (TextView) view.findViewById(R.id.targetName);
viewHolder.targetThumbnail = (ImageView) view.findViewById(R.id.targetThumbnail);
view.setTag(viewHolder);
} else
{
viewHolder = (ListViewHolder) convertView.getTag();
}
TargetDescriptor targetDescriptor = this.selectedTargets.get(position);
viewHolder.manufacturer.setText(targetDescriptor.manufacturer);
viewHolder.targetName.setText(targetDescriptor.targetName);
// At this point I pass the image view reference to my background task to load the image
LoadImageViewAsynchTask loadImageTask = new LoadImageViewAsynchTask(viewHolder.targetThumbnail, targetDescriptor);
loadImageTask.execute(new Integer[]
{ 64, 64 });
return view;
}
Run Code Online (Sandbox Code Playgroud)
编辑:那些使用eBay Android应用程序的人可以看到我正在寻找的效果,如果这有帮助.
ozn*_*nus 28
实际上有一种更简单的方法,你可以使用一个监听器:
mListView.setRecyclerListener(new AbsListView.RecyclerListener() {
@Override
public void onMovedToScrapHeap(View view) {
}
});
Run Code Online (Sandbox Code Playgroud)
不敢相信我有多愚蠢,这是一个非常容易解决的问题!
基本上在我的适配器中,如果要重新循环视图,我只需在重新使用视图之前将 ImageView 位图清空即可。这意味着在加载下一个图像之前列表视图项中的图像是空白的。当新图像在后台加载时,我不再遇到旧图像存在的问题。
我还在适配器中进行了更改,取消了绑定到视图的任何当前 AsynchTask,该视图可能仍在加载不再需要的先前图像。当我快速滚动列表视图时,这种情况非常普遍,通常会备份两个或多个图像加载,因此图像会在确定正确图像之前更改几次。
这是新代码,并对更改进行了注释,以便您可以看到发生了什么:
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ListViewHolder viewHolder;
// if this is not a recycled view then create a new view for the data...
if (convertView == null)
{
convertView = this.inflater.inflate(R.layout.target_list_view_layout, null, true);
viewHolder = new ListViewHolder();
viewHolder.manufacturer = (TextView) convertView.findViewById(R.id.manufacturer);
viewHolder.targetName = (TextView) convertView.findViewById(R.id.targetName);
viewHolder.targetThumbnail = (ImageView) convertView.findViewById(R.id.targetThumbnail);
convertView.setTag(viewHolder);
} else
{
viewHolder = (ListViewHolder) convertView.getTag();
// Cancel the previous attempt to load an image as this is going to be superceded by the next image
viewHolder.loadImageViewAsynchTask.cancel(true);
// Clear down the old image so when this view is displayed, the user does not see the old image before the
// new image has a chance to load in the background
viewHolder.targetThumbnail.setImageBitmap(null);
}
TargetDescriptor targetDescriptor = this.selectedTargets.get(position);
viewHolder.manufacturer.setText(targetDescriptor.manufacturer);
viewHolder.targetName.setText(targetDescriptor.targetName);
LoadImageViewAsynchTask loadImageViewAsynchTask = new LoadImageViewAsynchTask(viewHolder.targetThumbnail);
loadImageViewAsynchTask.setTargetDescriptor(targetDescriptor);
loadImageViewAsynchTask.execute(new Integer[]
{ 64, 64 });
// Keep a reference to the task so we can cancel it if the view is recycled next time round to prevent
// un-neccessary image loads that are out of date
viewHolder.loadImageViewAsynchTask = loadImageViewAsynchTask;
return convertView;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9267 次 |
| 最近记录: |