最近有一个需求,用一个八宫格显示图片,后台不断发送图片过来,每个格子的图片定时刷新,同时做渐变切换的效果。
同事用RecyclerView+自定义渐变效果的ItemAnimator实现这个效果,具体来说就是每次要切换图片时,调用notifyItemChanged()对应的格子。
但是效果不如预期,经常会出现前一张图片没有完全变成0透明度,导致两张图片看起来像是透明叠加在一起。
这里简单说一下RecyclerView的局部刷新逻辑:当调用notifyItemChanged()时,会先从内部的缓存池找change类型的缓存ViewHolder(缓存池会保存很多类型的ViewHolder),如果没有,会调用Adapter的onCreateViewHolder()创建一个新的ViewHolder,然后将新的ViewHolder和原来对应的局部的ViewHolder传入ItemAnimator中的animateChange()方法,在这个方法内对新旧Holder执行相应动画,同时将新的Holder传入Adapter的onBindViewHolder方法中,最后RecyclerView将新的Holder替换旧的Holder,旧的Holder则存入缓存池中对应change类型的缓存里。
后来通过测试证实,如果调用notifyItemChanged()较慢时,通过打印可以看到,就是两个不同的ViewHolder实例在不断的互相替换;但是如果调用速度过快,后面就会变成新、旧Holder都是同一个Holder,导致动画异常。
事实上,在源码默认的DefaultItemAnimator中,可以看到在animateChange()方法里有判断新旧Holder是否一致,若一致则调用animateMove()方法;而自定义的ItemAnimator则没有实现该功能。
虽然最后的解决方法是不用ItemAnimator,而改用TransitionDrawable来实现效果。但需要注意的是,如果往后需要使用ItemAnimator,最好在DefaultItemAnimator的基础上改,因为这东西坑还是蛮多的,一个完整的ItemAnimator要写的代码也不少。
评论