关于RecyclerView异步加载图片错位的小总结

1.总体思路

很明显这个问题在如今的Android开发中已经算不上问题,因为其产生原因,解决方法已经被讨论的非常成熟。这篇博客主要是自己在遇到问题到解决问题的的过程中,总结的一些可以帮助自己理清思路的小套路。

这里还是简单说明下问题原因及大致思路。RecyclerView,包括之前用的ListView都存在这个问题。因为有ViewHolder的重用机制,每一个item在移除屏幕后都会被重新使用以节省资源,避免滑动卡顿。而在图片的异步加载过程中,从发出网络请求到完全下载并加载成Bitmap的图片需要花费很长时间,而这时候很有可能原先需要加载图片的item已经划出界面并被重用了。而原先下载的图片在被加载进ImageView的时候没有判断当前的ImageView是不是原先那个要求加载的,故可能图片被加载到被重用的item上,就产生了图片错位的问题。解决思路也很简单,就是在下载完图片,准备给ImageView装上的时候检查一下这个ImageView
还是不是原来那个。

关键伪代码如下:

//给ImageView打上Tag作为特有标记
imageView.setTag(tag);

//下载图片
loadImage();

//根据tag判断是不是需要设置给ImageView
if(tag == iamgeView.getTag()) {
    imageView.setBitmapImage(iamge);
}

2.注意细节

实现起来难度不大,网上也都解释的很详细了,这里就不说怎么做了。就是一些细节和小技巧可能会需要注意一下。

  1. 给ImageView打的Tag可以就是图片的url,也可以加上position等位置参数
  2. 在加载图片的时候,一定要注意添加tag和判断tag的时机,从日志分析执行的先后顺序,理清逻辑。我就多次在这里踩坑了。比如图片已经下载完成了,但是重用的ImageView还没有覆盖新的tag。
  3. 我的ImageView是放在一个子布局 GridLayout里面,数量从0到9。在图片数量为0的时候,注意搞清楚后台返还的urls数组是null还是size()==0。
  4. 每次bindViewHolder时,GridLayout注意要removeAllViews()。这样比较简单粗暴,要优化还可以仅仅remove掉多余view,然后注意把剩下的view设置一个默认图片。
  5. 在没有加载到图片之前,设置默认的图片资源(我感觉对我用处不大,不过网上都建议这样做)
  6. 图片的大小:getWidth()这个方法所依赖的测量值是异步的,所以就有可能得到不准确的值,造成图片大小设置不恰当。

3.时间及事件梳理

因为自己在这里踩坑太多且花了很长时间才爬出来,所以着重记录一下。
开始->当前item1给ImageView打tag
->当前item1发起网络请求
->异步处理网络请求
->当前item1滑出屏幕
->划出屏幕的item重用并滑进屏幕命名为item2
->item2重新给ImageView打上tag
->item1的图片下载完成,因为重用的原因,图片将要加载给item2
->用原先传入的item1设置的tag和新覆盖的tag比较,发现不相同
->不给当前item2设置图片,避免了图片错位

4.代码

想了下,我写的太多关于自己布局和业务的东西,不适合单独拿出来说明问题,就不贴了。以后有空了单独写一个出来用作示例。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值