listView convertView缓存机制、异步加载图片问题剖析

2015年9月8日07:56:03 发表评论 4 views

先介绍下listView的convertView缓存机制 & 异步加载图片:

convertView缓存机制:我们假设一个屏幕一次显示8个item,当第9个item划进屏幕时,ListViewadapter说,返给我一个view,我要显示。adapter调用getView()方法,由于使用了convertView缓存机制,getView(),会在上一次new 出来的8个itemview中取出第一个itemview(这时因为不显示了,listview将其变成了convertview),并给了listview作为第9个item的view。

异步加载图片:如果我们不适用异步加载图片,那么必须要在每次getview()返回一个view前把view的iamgeview设置好了图片再返回给Listview,这意味着我必须等网络下载好了这个图片我才能返回给listview一个item,很明显,下滑效果是屏幕卡顿的半天没反应。但是使用异步加载,先让adapter返回一个view,view的iamgeview我先不确定,并开启一个新线程去下载图片,等图片下载好了,再去更新到这个view的imageview。当然了,一般只需要异步加载图片,而文字信息默认认为已经取得了,当然文字也是可以异步加载的。

但是,当我们使用了listView在通过 convertView缓存机制 & 异步加载图片时,若快速滑动屏幕,会发生图片闪顿2次以上的错图最后才能正确显示图片的现象。我们来剖析原因:

之所以会在下滑后,图片显示出一个之前的错图,是因为convertview的缓存,这个convertview的图片还是保持着上一次的图片,然而我这里的新线程还没来得及下载好并更新到这个imageview,你的老图片就已经显示上去了。所以造成了第一次的错图。但是这里不会出现闪!

然后快速下滑,发现第一个错图就要被正确的第二张图显示替换时,我又把屏幕下滑了,所以我又换了个图,第二次又错图了。我假设每个图片下载需要1s,由于我使每个异步线程人工阻塞了1s,那么上来有8个异步线程在运行(编号1-8),如果1s之内下滑了ListView比如说下滑了8个,那么新更新的8个item还是用的以前老view(不是新new出来的),并且又开启了8个异步线程(编号9-16)。因为之前显示了是老的图片。然后1-8号异步线程运行完毕,更新ImageView,所以出现了一次闪,紧跟着9-16异步线程运行完毕,又更新imageView,又出现了一次闪。最终显示正确结果。这就是下滑时先显示默认图片,再闪一下错误图片,最后闪一下正确图片的本质过程。这次是另一种错误原因。

所以,我们为了解决问题,分两步走:

1,在getview返回一个convertView之前,我把imageview设置为一个固定的图片(ic_launcher),覆盖掉convertview的老错图,这样就不会在显示时造成错图尴尬了。所以convertView缓存机制造成的错图原因得到解决,因为: 缓存造成的错图是无法避过的········

2.在把imageview设置为一个固定的图片(ic_launcher),覆盖掉convertview的老错图之后,我为ImageView设置了一个tag(url),tag里放的是一个唯一标识url,并且在异步线程里传入url,当线程下载好了后,先判断iamgeview的tag是不是我下载的这个url,如果是,说明主人还没有滑动,还在等我加载图片,那么我赶紧显示上去;如果tag!=url了,说明主人早已又滑了一段,我所在的convertView又被替换了一次,所以我还是别显示了!

  • yiisaa
  • 这是我的微信扫一扫
  • weinxin
  • zhengweiqiangcom
  • 我的微信公众号扫一扫
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: