7

背景

我正在使用PinterestLikeAdapterView 库来显示来自互联网的一些图像,这就像一个 gridView 但每个单元格的高度不同。

问题

因为我使用这个库来显示来自互联网的图像,所以在调用 notifyDatasetChanged 时不会导致视图混乱是至关重要的。

出于某种原因,调用此函数将调用 getView() 方法,并为视图提供不同的位置。例如,即使我根本没有滚动,并调用 notifyDatasetChanged(或 addAll,如果它是一个 ArrayAdapter),对于位置 0,它将采用位置 8 的视图,对于位置 1,它将采用位置视图7,以此类推……

这使得整个网格刷新它的图像,因此它破坏了用户体验。

通常,在gridView和listView中,克服刷新的方法是将视图使用的位置放在viewHolder中,如果相等,则表示它们仍然匹配。

例如:

... getView(...)
  {
  //<=inflate a new view if needed 
  //avoid refreshing view in case it's still the same position:
  if(position==holder.position)
    return rootView;
  holder.position=position;
  //<=update the view according to its data
  ...
  }

但是,在这里他们以不同的顺序重用其他视图,所以这个技巧在这里不起作用。

由于这个问题,我不仅刷新了几乎所有可见视图,而且由于我使用DiskCacheLru 库,它会崩溃,因为它尝试使用 2 个线程将 2 个相同的 inputSteam 数据放入同一个键中。

问题

我能做些什么?这是库中的已知错误吗?

也许我正在使用一种不好的方法来克服刷新?

现在,我使用内存缓存来至少获取以前缓存的项目,但这更像是“治愈”而不是“疫苗”......

4

4 回答 4

2

简短的回答

使用像Picasso这样的图像加载库,它将最近使用的图像缓存在内存中,因此不需要从网络重新加载它们。

长答案:

AdapterView做一些称为View回收的事情,其中Views​​不再需要显示一个位置被重新用于显示另一个位置。(例如,当您向下滚动时,Views从屏幕顶部消失的那些会被重新用于屏幕底部的新位置。)因此,对于多个位置getView()传递相同的值是正常的。View

这样做是出于性能原因:充气新品Views很难并且需要时间,因此AdapterView尽量少做。

使用持有人时,您将引用ImageViewTextView子项存储在 item 的View中,因此您不必findViewById()每次都查找它们 - 您通常不会存储特定位置的任何内容,因为 theView及其持有人通常是用于不同的位置。

现在,当您调用 时notifyDataSetChanged()AdapterView假设数据集已完全更改。与位置 8 相关联的图像可能不再存在,或者它现在可能与位置 12 相关联。因此,所有现有Views的都被废弃了——但因为AdapterView仍然想避免夸大 new Views,它们被重新用于显示新数据,而不考虑它们之前显示的位置。

这解释了为什么不同位置getView()的传递相同View,以及为什么在调用时会刷新可见位置notifyDataSetChanged()。但是如何避免让你的图像刷新,破坏用户体验呢?

使用像Picasso这样的图像加载库,它将最近使用的图像缓存在内存中,因此不需要从网络重新加载它们。刷新仍然会发生,但它会是即时的。

于 2013-10-19T18:19:26.853 回答
1

View getView(int position, View view, ViewGroup parent)在 .之后将始终按升序调用notifyDataSetChanged()
我想,完成下载任务的顺序会导致这个问题。
正如您在问题中提到的那样,保持职位是避免此问题的好方法。

这是解决它的另一种方法,也可以重用图像视图。

ImageView在下载任务中保留每个弱引用。
然后将下载任务包装在一个 dummyColorDrawable中。调用时,将 dummy 设置
为,然后开始下载。下载完成后,将下载的图像设置回.getViewColorDrawableImageViewImageViewOnPostExecute()

说明
http://android-developers.blogspot.jp/2010/07/multithreading-for-performance.html
源代码
https://code.google.com/p/android-imagedownloader/source/checkout

于 2013-10-09T03:22:51.747 回答
0

GitHub上的PinterestLikeListView上有一个很好的例子

这是图书馆StaggeredGridView

Android 的实验性 StaggeredGridView 的修改版本。包括自己的 OnItemClickListener 和 OnItemLongClickListener、选择器和固定位置恢复。

您可以在此处获取库项目

你可以在这里获得演示项目

这是一个非常好的开源项目,所以你可以使用 PinterestLikeAdapterView代替

在此处输入图像描述

希望这个图书馆能帮到你。

于 2013-10-20T15:38:19.783 回答
0

似乎这个库的作者已经修复了它,一段时间后我报告了它:

https://github.com/huewu/PinterestLikeAdapterView/issues/8

于 2013-12-11T07:36:53.740 回答