为 PinterestLikeAdapterView 调用 notifyDataSetChanged() 时如何避免刷新单元格? [英] How to avoid refreshing of cells on when calling notifyDataSetChanged() for PinterestLikeAdapterView?

查看:19
本文介绍了为 PinterestLikeAdapterView 调用 notifyDataSetChanged() 时如何避免刷新单元格?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using the PinterestLikeAdapterView library to show some images from the internet, which is like a gridView but with different height for each cell.

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

Since I use this library to show images from the internet, it's crucial that when calling notifyDatasetChanged won't cause a mess on the views.

出于某种原因,调用此函数将调用具有不同位置的视图的 getView() 方法.例如,即使我根本没有滚动,并调用 notifyDatasetChanged(或 addAll,以防它是 ArrayAdapter),对于位置 0,它将采用位置 8 的视图,对于位置 1,它将采用位置视图7 等等...

For some reason, calling this function would call the getView() method with different positions for the views. for example, even though i didn't scroll at all, and call notifyDatasetChanged (or addAll in case it's an ArrayAdapter), for position 0 it will take what was the view of position 8, for position 1 it will take the view of position 7 , and so on...

这会使整个网格刷新其图像,从而破坏用户体验.

This makes the whole grid to refresh its images, and so it ruins the UX.

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

Usually, in both gridView and listView, the way to overcome refreshing is to put the position that was used for the view inside the viewHolder, and if they are equal, it means that they still match.

例如:

... 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
  ...
  }

然而,这里他们以不同的顺序重用其他视图,所以这个技巧在这里不起作用.

However, here they re-use other views in a different order so this trick won't work here.

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

Because of this issue, not only i get refreshes of almost all of the visible views, but since i use DiskCacheLru library, it crashes since it tries to put 2 identical inputSteam data into the same key using 2 threads.

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

What can I do? Is this a known bug in the library?

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

Maybe I'm using a bad way to overcome refreshes?

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

for now, i use memory cache to at least get items that were cached before, but that's more like a "cure" than a "vaccine"...

推荐答案

简短回答:

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

Use an image loading library like Picasso that caches most recently used images in memory, so they don't need to be reloaded from the network.

长答案:

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

AdapterView does something called View recycling, where Views which are no longer needed to display a position are re-used to display another. (For example, as you scroll down, Views that disappear off the top of the screen are reused for new positions at the bottom of the screen.) Because of this, it's normal for getView() to be passed the same View for more than one position.

这样做是出于性能方面的考虑:扩充新的 Views 很困难并且需要时间,因此 AdapterView 尝试尽可能少地这样做.

This is done for performance reasons: Inflating new Views is hard and takes time, so AdapterView tries to do it as infrequently as possible.

当使用持有者时,你在项目的 View 中存储对 ImageViewTextView 子项的引用,所以你不必看每次都使用 findViewById() - 你通常不会存储任何特定于特定位置的东西,因为 View 及其持有者经常 用于不同的位置.

When using a holder, you store references to ImageView and TextView children inside the item's View, so you don't have to look them up with findViewById() each time - you don't usually store anything specific to a particular position, because the View and its holder will often be used for different positions.

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

Now, when you call notifyDataSetChanged(), AdapterView assumes that the data set has completely changed. The image that was associated with position 8 may no longer be present, or it may be associated with position 12 now. Consequently, all the existing Views are scrapped - but because AdapterView would still like to avoid inflating new Views, they're re-used to display the new data, with no regard for what position they were displaying previously.

这解释了为什么 getView() 为不同的位置传递相同的 View,以及为什么当您调用 notifyDataSetChanged()<时会刷新可见位置/代码>.但是如何避免让你的图片刷新,破坏用户体验?

This explains why getView() is being passed the same View for different positions, and why visible positions are being refreshed when you call notifyDataSetChanged(). But how to avoid having your images refresh, ruining the user experience?

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

Use an image loading library like Picasso that caches most recently used images in memory, so they don't need to be reloaded from the network. The refresh will still happen, but it'll be instantaneous.

这篇关于为 PinterestLikeAdapterView 调用 notifyDataSetChanged() 时如何避免刷新单元格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆