Android glide使用过程中遇到的坑(进阶篇)

之前有写过一篇关于glide的基本使用和相关配置,这篇就给大家分享一下glide在项目中通常会遇到的一些坑及解决方法

目前glide版本已经升级到了4.7.1,所以之前在用3.x版本的朋友,升级到最新版本的Api会有一些不一样的地方,详细不同地方可以参考官方介绍 https://muyangmin.github.io/glide-docs-cn/doc/migrating.html

最新版本配置环境:

implementation 'com.github.bumptech.glide:glide:4.7.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'

下面就来看看使用过程中遇到的坑,以下代码都是使用glide 4.7.1的api ,大家注意下。

当后台把用户的头像用地址前缀加用户ID拼接设计成时,往往修改头像后,再用Glide加载会发现头像还是之前的头像,原因很简单,是由于Glide默认加载了缓存的图片,所以导致更改之后地址没变还是加载之前的图片,如需要不加载缓存图片,可以使用如下代码:

    public static void display(ImageView imageView, String url) {
        if (imageView == null) return;
        Glide.with(imageView.getContext())
                .load(url)
                .apply(new RequestOptions()
                .dontAnimate()
                .skipMemoryCache(true)
                .diskCacheStrategy(DiskCacheStrategy.NONE))
                .into(imageView);
    }

设置圆角图片时,正好布局文件中用到了自定义圆角控件,这时应该这样处理代码如下:

    /**
     * 设置圆角
     * @param imageView
     * @param path
     * @param dp  圆角度数 90dp宽高一致时为圆形
     */
    public static void displayRound(ImageView imageView, String url, int dp) {
        RequestOptions options = new RequestOptions()
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .transforms(new CenterCrop(), new GlideRoundTransform(dp));
        Glide.with(imageView.getContext()).load(url)
                .apply(options)
                .transition(new DrawableTransitionOptions().crossFade())
                .into(imageView);
    }

    public class GlideRoundTransform extends BitmapTransformation {

        private static float radius = 0f;

        public GlideRoundTransform() {
            this(4);
        }

        public GlideRoundTransform(int dp) {
            radius = Resources.getSystem().getDisplayMetrics().density * dp;
        }

        @Override
        protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
            return roundCrop(pool, toTransform);
        }

        private static Bitmap roundCrop(BitmapPool pool, Bitmap source) {
            if (source == null) return null;
            Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
            if (result == null) {
                result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
            }
            Canvas canvas = new Canvas(result);
            Paint paint = new Paint();
            paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
            paint.setAntiAlias(true);
            RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());
            canvas.drawRoundRect(rectF, radius, radius, paint);
            return result;
        }


        public String getId() {
            return getClass().getName() + Math.round(radius);
        }

        @Override
        public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {

        }
    }

加载大图时会有可能出现OOM,可以控制高宽尺寸来处理,高宽设置一个合理的尺寸即可

    public static void display(ImageView imageView, String url) {
        if (imageView == null) return;
        Glide.with(imageView.getContext())
                .load(url)
                .apply(new RequestOptions()
                .override(180, 180))
                .into(imageView);
    }

第一次加载图片可能会出现拉伸变形,设置.dontAnimate()取消动画即可解决

    public static void display(ImageView imageView, String url) {
        if (imageView == null) return;
        Glide.with(imageView.getContext())
                .load(url)
                .apply(new RequestOptions().dontAnimate())
                .into(imageView);
    }

当占位图的ScaleType和图片的ScaleType不一致时,占位图和图片就会有一个ScaleType不对,怎么解决呢,我这边是通过listener巧妙的解决了这个问题,代码如下:

    public static void display(ImageView imageView, String url) {
        Glide.with(imageView.getContext()).load(url)
                .listener(new SGlideRequestListener(imageView, ImageView.ScaleType.FIT_XY, ImageView.ScaleType.CENTER_CROP))
                .transition(new DrawableTransitionOptions().crossFade())
                .into(imageView);
    }

    static class SGlideRequestListener implements RequestListener<String, GlideDrawable> {
        private ImageView.ScaleType mPlaceScaleType;
        private ImageView.ScaleType mActualScaleType;
        private ImageView mImageView;

        SGlideRequestListener(ImageView mImageView, ImageView.ScaleType placeScaleType, ImageView.ScaleType actualScaleType){
            this.mPlaceScaleType = placeScaleType;
            this.mActualScaleType = actualScaleType;
            this.mImageView = mImageView;
            mImageView.setScaleType(placeScaleType);
        }
        @Override
        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
            mImageView.setScaleType(mPlaceScaleType);
            return false;
        }

        @Override
        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
            mImageView.setScaleType(mActualScaleType);
            return false;
        }
    }

当需要提前预下载好图片, 可以使用preload()方法

    public static void preloadImage(String url) {
        if (TextUtils.isEmpty(url)) {
            return;
        }
        Glide.with(SSTApplication.getContext())
                .load(url)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .preload();
    }

当需要通过url获取缓存文件对象时

    private static File getCachedFile(String url) {
        if (TextUtils.isEmpty(url)) {
            return null;
        }
        File localFile = DiskLruCacheWrapper.get(Glide.getPhotoCacheDir(SSTApplication.getContext()),
                DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE).get(new OriginalKey(url, EmptySignature.obtain()));
        Logger.d(TAG,localFile!=null?localFile.getAbsolutePath():"null");
        return localFile;
    }

    static class OriginalKey implements Key {
        private final String id;
        private final Key signature;
        private OriginalKey(String id, Key signature) {
            this.id = id;
            this.signature = signature;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            OriginalKey that = (OriginalKey) o;
            return id.equals(that.id) && signature.equals(that.signature);
        }

        @Override
        public int hashCode() {
            int result = id.hashCode();
            result = 31 * result + signature.hashCode();
            return result;
        }

        @Override
        public void updateDiskCacheKey(MessageDigest messageDigest) throws UnsupportedEncodingException {
            messageDigest.update(id.getBytes(STRING_CHARSET_NAME));
            signature.updateDiskCacheKey(messageDigest);
        }
    }

根据url判断图片是否下载

File localFile = DiskLruCacheWrapper.get(Glide.getPhotoCacheDir(SSTApplication.getContext()),
                DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE).get(new OriginalKey(url, EmptySignature.obtain()));
return localFile!=null;

清除当前url的缓存

File localFile = DiskLruCacheWrapper.get(Glide.getPhotoCacheDir(SSTApplication.getContext()),
                DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE).get(new OriginalKey(url, EmptySignature.obtain()));
if(file != null)
      file.delete();

通过自定义View实现Fresco的viewAspectRatio宽高比功能

public class SImageView extends AppCompatImageView {
    private float mAspectRatio = 0;
    public SImageView(Context context) {
        this(context,null);
    }

    public SImageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public SImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        final TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.SImageView);
        if(typedArray != null) {
            if (typedArray.hasValue(R.styleable.SImageView_viewAspectRatio)) {
                mAspectRatio = typedArray.getFloat(R.styleable.SImageView_viewAspectRatio,0);
            }
            typedArray.recycle();
        }
    }

    public void setAspectRatio(float aspectRatio){
        if(mAspectRatio != 0) {
            mAspectRatio = aspectRatio;
            requestLayout();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if(mAspectRatio != 0) {
            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = (int) (width / mAspectRatio);
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

attrs.xml

<declare-styleable name="SImageView">
      <attr name="viewAspectRatio" format="float"/>
</declare-styleable>

布局文件中只要在SImageView设置app:viewAspectRatio属性即可,
如:

<com.soaic.widget.SImageView
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:viewAspectRatio="2"  />

OK, 以上就是我在项目中遇到的一些坑及解决方法,希望对大家有所帮助!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容