1

正如标题所说,我使用 BaseAdapter 在 ListView 中显示项目。显然 ListView 将重用视图,包括 TextViews 和 NetworkImageViews。

假设一次可以显示 3 个项目,则 NetworkImageView 将被重新用于索引处的项目:1、4、7、...。

根据显示的内容,NetworkImageView 将:

  1. 从网络请求图像并显示它,
  2. 显示缓存的位图,
  3. 或显示本地可绘制资源。

项目 2 和 3 工作正常,但是在场景 1 中,假设我们从网络显示索引 4 处的项目,并且用户在加载 4 之前滚动到项目 7 并且它是本地资源,我们显示本地资源。然而,我们的网络图像请求现在可能刚刚完成,所以我们最终显示了一个不正确的图像。

如何执行正确的(预期的)行为?

4

3 回答 3

5

@Snicolas 的答案是正确的,但缺乏一些关于如何实际实现这一点的指示。所以这里。

总体思路是跟踪每一行正在进行的图像请求。这样,当您遇到回收的行时,您可以取消挂起的请求并为与该行相关的新数据启动一个新请求。

实现此目的的一种直接方法是使ImageContainer您在请求图像加载时可以取回的内容成为适配器的 ViewHolder/RowWrapper 的一部分。如果您还没有使用这种模式,那么您应该这样做。那里有很多例子,包括一个很好的 I/O 演讲。

将其添加ImageContainer到您的持有人后,发出图像请求并存储您返回的容器。有点像这样:

ImageListener listener = ImageLoader.getImageListener(holder.imageview, defaultImageResId, errorImageResId);
holder.mImageContainer = ImageLoader.get(url, listener);

下次在适配器的getView()方法中出现回收行时,您可以从其中取回您的支架并检查它是否ImageContainer有一套。以下 3 种情况之一可能适用:

  • 没有ImageContainer,这意味着您可以提出新的图像请求。
  • 有一个ImageContainer,它正在加载的 url 与新行数据相同。在这种情况下,您无需执行任何操作,因为它已经在加载您所追求的图像。
  • 有一个ImageContainer但它正在加载的 url 与新的行数据不同。在这种情况下,取消请求并为当前行数据创建一个新的请求。

如果您愿意,您可以通过BaseAdapter实现扩展来移动其中的一些逻辑AbsListView.RecyclerListener(并将适配器设置为ListViewor的回收器侦听器GridView)。该onMovedToScrapHeap(View view)方法在刚刚被回收的视图中传递,这意味着您可以在其中取消任何挂起的图像请求。

于 2013-08-18T22:36:16.813 回答
3

如果您使用提供的 NetworkImageView,则无需强制执行任何操作。

NetworkImageView 检测它何时被回收并自动取消请求。

于 2013-08-20T18:40:46.350 回答
-1

我不知道这个 API,但我猜你应该在回收这样的视图之前取消任何待处理的请求。你怎么能做到这一点我不能说。

你有没有像这样的替代品:

于 2013-08-18T19:49:24.297 回答