我正在使用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数据放入同一个键中。
我该怎么办? 这是库中的已知错误吗?
也许我用一种糟糕的方法来克服刷新?
现在,我使用内存缓存至少获取之前缓存的项目,但这更像是“治愈”而不是“疫苗”......
答案 0 :(得分:2)
简短回答:
使用像Picasso这样的图像加载库来缓存内存中最近使用过的图像,因此不需要从网络重新加载它们。
答案很长:
AdapterView
会执行名为View
回收的内容,其中不再需要显示位置的Views
来重新显示另一个位置。 (例如,当您向下滚动时,屏幕顶部消失的Views
将重新用于屏幕底部的新位置。)因此,{{1}正常为多个职位传递相同的getView()
。
这样做是出于性能原因:充斥新的View
很难并且需要时间,所以Views
会尽可能少地尝试。{/ p>
使用持有人时,您可以在AdapterView
ImageView
内存储对TextView
和View
个孩子的引用,因此您无需查看每次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
希望这个图书馆能够帮助你。
答案 3 :(得分:0)
似乎该库的作者已经修复了它,经过一段时间我已经报道了它: