如何在为PinterestLikeAdapterView调用notifyDataSetChanged()时避免刷新单元格?

时间:2013-10-08 09:17:00

标签: android android-gridview pinterest notifydatasetchanged

背景

我正在使用PinterestLikeAdapterView library来显示来自互联网的一些图像,这些图像就像一个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 library,它崩溃了,因为它试图使用2个线程将2个相同的inputSteam数据放入同一个键中。

问题

我该怎么办? 这是库中的已知错误吗?

也许我用一种糟糕的方法来克服刷新?

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

4 个答案:

答案 0 :(得分:2)

简短回答

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

答案很长:

AdapterView会执行名为View回收的内容,其中不再需要显示位置的Views来重新显示另一个位置。 (例如,当您向下滚动时,屏幕顶部消失的Views将重新用于屏幕底部的新位置。)因此,{{1}正常为多个职位传递相同的getView()

这样做是出于性能原因:充斥新的View很难并且需要时间,所以Views会尽可能少地尝试。{/ p>

使用持有人时,您可以在AdapterView ImageView内存储对TextViewView个孩子的引用,因此您无需查看每次findViewById() - 您通常不会存储特定位置的特定内容,因为View及其持有者经常会用于不同的位置。

现在,当您致电notifyDataSetChanged()时,AdapterView会认为数据集已完全更改。与位置8相关联的图像可能不再存在,或者现在可能与位置12相关联。因此,所有现有的Views都被废弃了 - 但由于AdapterView仍希望避免让新的Views充气,因此他们会重新使用它们来显示新数据,而不考虑他们之前显示的位置。

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

使用像Picasso这样的图像加载库来缓存内存中最近使用过的图像,因此不需要从网络重新加载它们。刷新仍然会发生,但它会瞬间完成。

答案 1 :(得分:1)

View getView(int position, View view, ViewGroup parent)之后,

notifyDataSetChanged()将始终以递增方式调用 我想,完成下载任务的顺序会导致这个问题 正如您在问题中提到的那样,保持这个位置是避免这个问题的好方法。

这是解决它的另一种方法,也可以重复使用imageviews。

在下载任务中保留每个ImageView的弱引用 然后将下载任务包装在虚拟ColorDrawable中 调用getView后,将虚拟ColorDrawable设置为ImageView,然后开始下载。下载完成后,将下载的图像设置回ImageView中引用的OnPostExecute()

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

答案 2 :(得分:0)

GitHub

中的 PinterestLikeListView 有一个很好的例子

这是图书馆 StaggeredGridView

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

您可以在此处获取图书馆项目library

您可以获得演示项目Here

这是一个非常好的开源项目,因此您可以使用而不是 PinterestLikeAdapterView

enter image description here

希望这个图书馆能够帮助你。

答案 3 :(得分:0)

似乎该库的作者已经修复了它,经过一段时间我已经报道了它:

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