【问题标题】:Android Volley - Cancel NetworkImageView request in Base AdapterAndroid Volley - 在基本适配器中取消 NetworkImageView 请求
【发布时间】:2013-08-18 19:21:35
【问题描述】:

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

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

根据显示的内容,NetworkImageView 将:

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

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

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

【问题讨论】:

    标签: android android-volley


    【解决方案1】:

    @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(并将适配器设置为ListViewGridView 的回收器侦听器)来移动其中的一些逻辑。 onMovedToScrapHeap(View view) 方法在刚刚被回收的视图中传递,这意味着您可以在其中取消任何待处理的图像请求。

    【讨论】:

    • @Pork 的答案是正确的,但对于不使用NetworkImageView 时,这是非常有用的信息。如果有人需要进一步控制视图,还有关于使用 AbsListView.RecyclerListener 的好信息。 +1
    • 感谢您的回答,我只是有一个疑问,您如何取消使用 ImageLoader 中的 get 方法发出的请求?您不能为这些请求添加标签,这是您取消请求所需要的。
    • 没关系,我已经看到 ImageContainer 类有自己的方法来取消要保存的图像的请求。
    【解决方案2】:

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

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

    【讨论】:

    • 不幸的是,这实际上并没有回答问题。在类似 ListView 的适配器中,相应的视图会被回收,因此它永远不会分离。
    • 如果你不介意的话,你能告诉我发生了什么吗? Volley 的一件事是没有“发布”或版本号,所以可能只是我使用的是旧版本。
    • 当视图被回收时,您必须在适配器的 getView 中为 NetworkImageView 设置一个新值。此时,NetworkImageView 将终止旧请求。这是作为回收过程的一部分发生的,因此如果他们使用 NetworkImageView,OP 描述的情况将永远不会发生。您说 NetworkImageView 在从列表视图中分离时不会取消请求是正确的,只有在它被回收后,请求才会停止。我已经更新了我的答案,谢谢。
    【解决方案3】:

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

    你有没有类似的替代品:

    【讨论】:

      猜你喜欢
      • 2013-07-03
      • 2015-05-17
      • 2013-05-22
      • 2019-12-13
      • 2016-05-09
      • 2017-04-09
      • 2015-07-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多