RecyclerView使用Glide加载图片刷新闪烁问题记录

一、起因

        我们在项目中需要经常使用RecyclerView,但是刷新的时候闪烁确不经常见。我在做项目的过程中,使用Gilde库进行加载图片,根据产品设计,列表中的图片是需要圆角的,并且有些地方是需要局部圆角的,于是我在网上找了一个RoundCornersTransformation的工具类,可以对部分地方进行圆角绘制,对于单张图片的加载是没有问题的,但是后来使用RecyclerView进行notifyDataSetChanged刷新时,问题就悄无声息的发生了。天啊!这闪烁的节奏感,赶紧嗨起来!

二、经过

        我第一时间对所写的代码进行了地毯式的排查,首先怀疑到了RecyclerView上面了,对于网上说的是众说纷纭:
①自定义DefaultItemAnimator:这里就不细说了,详见:

RecyclerView刷新闪烁问题_u013346208的博客-CSDN博客_recyclerview刷新数据闪烁

②还有各种设置例如:

((SimpleItemAnimator)RecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
Adapter.setHasStableIds(false);
RecyclerView.getItemAnimator().setChangeDuration(0);
经过如上的排查,哎嘿,你猜怎么着,压根就没有管用。
于是我就赶紧换方案,改用排除法,如果是RecyclerView导致的图片闪烁,那么加载资源文件里面的图片也应该是列表刷新闪烁的,但是经过多次实验排查,并非想像中的那样,一点也没有闪烁。这时,我就感到此时离真相已经不远了。。。

三、结果

        既然已经进入了这个阶段,我就怀疑到了RoundCornersTransformation工具类。经过查看官方文档,终于找到了真相。

必须得实现如下的三个函数:
equals(Object o)
hashCode()
updateDiskCacheKey(MessageDigest messageDigest)
这三个函数实现后,终于不闪烁了,问题解决了,希望让更多的人能从此脱坑,走上人生巅峰。

public class RoundCornersTransformation implements Transformation<Bitmap> {
    private final String ID = "com. bumptech.glide.transformations.FillSpace";
    private final byte[] ID_ByTES = ID.getBytes(CHARSET);

    private BitmapPool mBitmapPool;
    private int mRadius;
    private int mDiameter;
    private CornerType mCornerType = CornerType.ALL;


    public RoundCornersTransformation(Context context, int radius, CornerType type) {
        mBitmapPool = Glide.get(context).getBitmapPool();
        mCornerType = type;
        mRadius = radius;
        mDiameter = 2 * mRadius;
    }

    public enum CornerType {
        /**
         * 所有角
         */
        ALL,
        /**
         * 左上
         */
        LEFT_TOP,
        /**
         * 左下
         */
        LEFT_BOTTOM,
        /**
         * 右上
         */
        RIGHT_TOP,
        /**
         * 右下
         */
        RIGHT_BOTTOM,
        /**
         * 左侧
         */
        LEFT,
        /**
         * 右侧
         */
        RIGHT,
        /**
         * 下侧
         */
        BOTTOM,
        /**
         * 上侧
         */
        TOP,
    }

    @Override
    public Resource<Bitmap> transform(@NonNull Context context, @NonNull Resource<Bitmap> resource, int outWidth, int outHeight) {
        Bitmap source = resource.get();
        int width = source.getWidth();
        int height = source.getHeight();
        Bitmap bitmap = mBitmapPool.get(width, height, Bitmap.Config.ARGB_8888);
        if (bitmap == null) {
            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        }
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
        drawRoundRect(canvas, paint, width, height);
        return BitmapResource.obtain(bitmap, mBitmapPool);
    }

    private void drawRoundRect(Canvas canvas, Paint paint, float width, float height) {
        switch (mCornerType) {
            case LEFT_TOP:
                drawLeftTopCorner(canvas, paint, width, height);
                break;
            case LEFT_BOTTOM:
                drawLeftBottomCorner(canvas, paint, width, height);
                break;
            case RIGHT_TOP:
                drawRightTopCorner(canvas, paint, width, height);
                break;
            case RIGHT_BOTTOM:
                drawRightBottomCorner(canvas, paint, width, height);
                break;
            case LEFT:
                drawLeftCorner(canvas, paint, width, height);
                break;
            case RIGHT:
                drawRightCorner(canvas, paint, width, height);
                break;
            case BOTTOM:
                drawBottomCorner(canvas, paint, width, height);
                break;
            case TOP:
                drawTopCorner(canvas, paint, width, height);
                break;
            case ALL:
            default:
                canvas.drawRoundRect(new RectF(0, 0, width, height), mRadius, mRadius, paint);
                break;
        }
    }


    /**
     * 画左上角
     */
    private void drawLeftTopCorner(Canvas canvas, Paint paint, float width, float height) {
        canvas.drawRect(new RectF(mRadius, 0, width, height), paint);
        canvas.drawRect(new RectF(0, mRadius, mRadius, height), paint);
        canvas.drawArc(new RectF(0, 0, mDiameter, mDiameter), 180, 90, true, paint);
    }

    /**
     * 画左下角
     */
    private void drawLeftBottomCorner(Canvas canvas, Paint paint, float width, float height) {
        canvas.drawRect(new RectF(0, 0, width, height - mRadius), paint);
        canvas.drawRect(new RectF(mRadius, height - mRadius, width, height), paint);
        canvas.drawArc(new RectF(0, height - mDiameter, mDiameter, height), 90, 90, true, paint);
    }

    /**
     * 画右上角
     */
    private void drawRightTopCorner(Canvas canvas, Paint paint, float width, float height) {
        canvas.drawRect(new RectF(0, 0, width - mRadius, height), paint);
        canvas.drawRect(new RectF(width - mRadius, mRadius, width, height), paint);
        canvas.drawArc(new RectF(width - mDiameter, 0, width, mDiameter), 270, 90, true, paint);
    }

    /**
     * 画右下角
     */
    private void drawRightBottomCorner(Canvas canvas, Paint paint, float width, float height) {
        canvas.drawRect(new RectF(0, 0, width, height - mRadius), paint);
        canvas.drawRect(new RectF(0, height - mRadius, width - mRadius, height), paint);
        canvas.drawArc(new RectF(width - mDiameter, height - mDiameter, width, height), 0, 90, true, paint);
    }

    /**
     * 画左 角
     */
    private void drawLeftCorner(Canvas canvas, Paint paint, float width, float height) {
        canvas.drawRect(new RectF(mRadius, 0, width, height), paint);
        canvas.drawRect(new RectF(0, mRadius, mRadius, height - mRadius), paint);
        canvas.drawArc(new RectF(0, 0, mDiameter, mDiameter), 180, 90, true, paint);
        canvas.drawArc(new RectF(0, height - mDiameter, mDiameter, height), 90, 90, true, paint);
    }

    /**
     * 画右角
     */
    private void drawRightCorner(Canvas canvas, Paint paint, float width, float height) {
        canvas.drawRect(new RectF(0, 0, width - mRadius, height), paint);
        canvas.drawRect(new RectF(width - mRadius, mRadius, width, height - mRadius), paint);
        canvas.drawArc(new RectF(width - mDiameter, 0, width, mDiameter), 270, 90, true, paint);
        canvas.drawArc(new RectF(width - mDiameter, height - mDiameter, width, height), 0, 90, true, paint);
    }

    /**
     * 画上 角
     */
    private void drawTopCorner(Canvas canvas, Paint paint, float width, float height) {
        canvas.drawRect(new RectF(0, mRadius, width, height), paint);
        canvas.drawRect(new RectF(mRadius, 0, width - mRadius, mRadius), paint);
        canvas.drawArc(new RectF(0, 0, mDiameter, mDiameter), 180, 90, true, paint);
        canvas.drawArc(new RectF(width - mDiameter, 0, width, mDiameter), 270, 90, true, paint);
    }

    /**
     * 画下 角
     */
    private void drawBottomCorner(Canvas canvas, Paint paint, float width, float height) {
        canvas.drawRect(new RectF(0, 0, width, height - mRadius), paint);
        canvas.drawRect(new RectF(mRadius, height - mRadius, width - mRadius, height), paint);
        canvas.drawArc(new RectF(0, height - mDiameter, mDiameter, height), 90, 90, true, paint);
        canvas.drawArc(new RectF(width - mDiameter, height - mDiameter, width, height), 0, 90, true, paint);
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof RoundCornersTransformation) {
            RoundCornersTransformation other = (RoundCornersTransformation) o;
            return mRadius == other.mRadius;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Util.hashCode(ID.hashCode(), Util.hashCode(mRadius));
    }

    @Override
    public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
        messageDigest.update(ID_ByTES);
        byte[] radiusData = ByteBuffer.allocate(4).putInt((int) mRadius).array();
        messageDigest.update(radiusData);
    }
}

补充一下:在Glide中不要忘了加上skipMemoryCache(false)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值