知道ListView中的View何时离开了屏幕?

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)

  • 对于"了解ListView中的视图何时离开屏幕"这一问题,这实际上是最佳答案.但看起来原作者真的只需知道视图何时被回收. (2认同)

Jus*_*ips 3

不敢相信我有多愚蠢,这是一个非常容易解决的问题!

基本上在我的适配器中,如果要重新循环视图,我只需在重新使用视图之前将 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)