ListView加载图片错位

什么导致图片错乱?怎么解决?

错乱的原因是异步加载以及Convertview对象复用造成的。

首先给ImageView设置一个Tag,这个Tag中设置的是图片的Url,   

  然后在加载的时候取得这个Url要和加载的那个Position中Url对比,   

如果不同就加载,相同的话就复用以前的,不加载。


原理:

一个屏幕显示了几条,会在下面默认绘制一条默认的,例显示了4条

当第一条移出屏幕的时候会将这一条目给6条使用,

每当有新的元素进入界面时就会回调getView()方法,而在getView()方法中会开启异步请求从网络上获取图片(注意:网络操作都是比较耗时的),也就是说当我们快速滑动ListView的时候就很有可能出现这样一种情况,某一个位置上的元素进入屏幕后开始从网络上请求图片,但是还没等图片下载完成,它就又被移出了屏幕。这种情况下会产生什么样的现象呢?根据ListView的工作原理,被移出的条目将很快会被新进入屏幕的条目所复用,而如果在这个时候刚好前面发起的图片请求有了响应,就会将已经移出的条目上要显示的图片加载到当前位置上,因为虽然它们位置不同,但都是共用的同一个ImageView实例,这样的话就出现了图片乱序的情况。

解决方案一  使用findViewWithTag

其实就是在getview方法里面,给imageview用setTag设置一个tag

这个setTag()方法,可以把当前位置图片的URL地址作为参数传了进去,这个是为后续的findViewWithTag()方法做准备。在onPostExecute()方法当中通过ListView的findVIewWithTag()方法来去获取ImageView控件的实例。获取到控件实例后判断下是否为空,如果不为空就让图片显示到控件上。

因为ListView中的ImageView控件都是重用的,移出屏幕的控件很快会被进入屏幕的图片重新利用起来,那么getView()方法就会再次得到执行,而在getView()方法中会为这个ImageView控件设置新的Tag,这样老的Tag就会被覆盖掉,于是这时再调用findVIewWithTag()方法并传入老的Tag,就只能得到null了,而我们判断只有ImageView不等于null的时候才会设置图片,这样图片乱序的问题也就不存在了。

解决方案二  使用NetworkImageView

NetworkImageView是Volley当中提供的控件

将xml布局中将Imageview换成NetworkImageView,

setDeafaultImageResld():占位图

setErrorImageResld():加载图片出错的图

setImageUrl():显示所要的图片

可以设置默认的占位图,设置加载图片出错的图片,可以用第三个方法加载要显示的正确的图片

ImageContainer对象中获取封装的图片请求地址,并拿来和当前的请求地址做对比,如果相同,就说明这是一条重复的请求,就直接return掉;如果不同,就调用cancelRequest()方法将请求取消,然后将这张图片设置为默认的,然后再发送一遍请求


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章