关于在RecyclerView中使用UniversalImageLoader加载图片刷新数据时引起的闪烁问题

关于在RecyclerView中使用UniversalImageLoader加载图片刷新数据时引起的闪烁问题

先上一张效果图:
效果图

这个是我在用RecyclerView借助了ItemTouchHelper的帮助下实现的一个拖拽效果。我在成功拖拽完毕后调用notifyDatasetChanged进行数据更新时出现了图片闪烁一下的情况。
然后就开始在网上找解决办法。最终都没有达到预期的效果,但也不是说网上的办法不行,在此,我总结除了一下几点:
1.如果不是用的UIL框架加载图片,而是采用原生的imageView.setImage的方式加载而在调用notifyDatasetChanged或者notifyItemRangeChanged(start,end)出现刷新整个数据时而产生的闪烁,这里可以归结于RecyclerView自身的因素。
解决办法:
(1)尽量给每个item设置单独的id,也就是在adapter中要setHasStableIds(true),然后在getItemId中返回你的item的id.谷歌首先是很推荐用户使用这个方法的,设置了id后还会解决position错位等很多莫名奇妙的问题。
(2)关闭RecyclerView的默认Item动画效果。

((DefaultItemAnimator)recyclerView.getAnimator()).setSupportsChangeAnimations(false);

上面的方法都能很好地解决自身因素产生地闪烁问题。

2.采用UIL框架产生的闪烁。
首先这个应该是UIL自己的加载机制而产生的问题。UIL可以有多级缓存加载。直接在绑定Viewholder的时候进行Display方法的显示,会在holder复用的时候不断调用多级加载的过程,一班来讲会由内存缓存到磁盘缓存的过渡。我没有具体研究过整个加载流程是怎样的,但是毫无疑问,和普通的imageView.setImage的方式比起来,要复杂得多。其实我在关闭内存缓存进行加载的时候,发现在刷新数据时,UIL先显示的是你在配置项里面的默认图片,然后才显示真正的图片,虽然时间比较短,但是过渡瞬间还是比较清除的。接着我开启了内存缓存,然后没有看见默认图片,而是闪烁一下。在这里,我可以大胆推测:
(1)内存缓存的加载速度远远大于磁盘缓存
(2)闪烁实际上也是进行了默认图片到真实图片的过渡,只不过,内存缓存加载的速度远远大于磁盘缓存,导致默认图片都没显示完就直接显示真实图片了,但是毕竟是过渡,还是有时间差了,所以产生了闪烁。

为此,为了验证我的猜想,特意写了下面的这个方法:

/**
     * 重定义UIL显示图片的方式<br>
     *     UIL可以有多级缓存,(内存缓存,磁盘缓存)。
     *     直接通过display方法显示图片,在一般的操作中是完全OK的。但是如果涉及到RecyclerView的数据全量更新,
     *     如{@link RecyclerView.Adapter#notifyDataSetChanged()}或者{@link android.support.v7.widget.RecyclerView.Adapter#notifyItemChanged(int)}
     *     之类的方法时,会闪烁。网上的说法很繁杂,有说是RecyclerView自带的item动画效果之类引起的等等。结果排查发现
     *     是UIL自身加载图片的机制引起的。这个方法可以解决闪烁的问题。
     * @param view
     * @param imgUrl
     * @param option
     */
    public void showImage(ImageView view, String imgUrl, DisplayImageOptions option){
        //确保当前的加载配置里面配置了内存缓存true
        Bitmap bmp= ImageLoader.getInstance().getMemoryCache().get(imgUrl);
        if(bmp!=null){
            view.setImageBitmap(bmp);
        }else{
            //确保当前的加载配置里面配置了磁盘缓存true
            File cache=ImageLoader.getInstance().getDiskCache().get(imgUrl);
            if(cache!=null){
                //这里根据具体地需要,可以自己定义Bitmap的压缩项,不过一般无需再次定制
                //UIL的初始配置就已经决定了压缩结果,效果还是比较好的,直接decode就行了
                view.setImageBitmap(BitmapFactory.decodeFile(cache.getAbsolutePath()));
            }else{
                //如果前面两项都没有,证明图片还没有被缓存过,老实地用传统方法加载吧
                ImageLoader.getInstance().displayImage(imgUrl,view, option);
            }
        }
    }

现在,再让我们来看看效果:
这里写图片描述

完美,不再出现闪烁。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值