【图片加载】Glide的使用以及遇到的一些坑

来源:互联网 发布:免费淘宝一键复制宝贝 编辑:程序博客网 时间:2024/05/16 00:45

最近项目用Glide来加载图片,也遇到了一些问题,这里记录总结下。Demo代码点这里

一、Glide简单使用

Glide的Github地址这里,使用比较简单,直接在Gradle里引入

compile 'com.github.bumptech.glide:glide:3.7.0'

最简单的使用,这四个也是最基础必备的

Glide.with(this).load(url).into(imageView);

正常来说还要有占位图,错误图,大小,缓存啊等等一系列配置,都可以像上面一样一条链自由组合,简单说下Glide的一些常用方法。
1.with()
with提供了几种构造方法,可以在源码里看,有Context, Activity, Fragment等,如果传入Application.this作为参数时,Glide的加载不受当前Activity生命周期影响,但这会导致即使Activity结束后,仍然继续加载图片。
2.load()
load可以加载网络图片链接,也可以加载本地图片地址,以及resourceId, File等等
3.into()
into直接传入ImageView;
4.placeholder()
在加载过程中设置占位图,可以传入Drawable或resouceId
5.error()
加载失败显示的图片,可以传入Drawable或resouceId
6.override(int width, int height)
设置加载图片的宽高,像素为单位,在自定义ImageView大小或者计算瀑布流高度时,偶尔会用到。
7.dontAnimate()
Glide加载时默认会有淡入淡出的加载效果,该方法可以去掉动画效果,直接显示图片
8..skipMemoryCache(true)
跳过图片缓存
9.diskCacheStrategy(DiskCacheStrategy.ALL)
设置缓存策略,可选的参数有 :ALL(缓存所有数据), NONE(不缓存), SOURCE(只缓存源数据), RESULT(只缓存转换后的数据);
10.priority(Priority.NORMAL)
加载优先级,优先级越高越先加载
11.crossFade(int duration)
加载时淡入淡出动画时间,也可以不传,默认300ms
12.animate()
自定义加载动画
13.thumbnail(0.1f)
设置缩略图,先加载缩略图再加载完整图片,在大量的图片流列表里,这个方法还是挺好用的, 快速滑动列表时,不致于出现大量的空白.
14.asBitmap()
把图片当成bitmap对待,如果是Gif时会停留在第一帧
15.asGif()
加载GIF图片,不加该方法时,也可以加载GIF;加了该方法,如果资源不是GIF,会加载失败。
16.bitmapTransform()
对图片进行转换,只能用于bitmap
17.transform()
对图片进行转换
16.Glide.get(this).clearDiskCache()
清理磁盘缓存,需要在子线程中执行
17.Glide.get(this).clearMemory();
清理内存缓存,可以直接在主线程执行

二、遇到的一些问题

1. 圆形图片设置占位图后第一次只显示占位图,第二次才正常显示
这个问题比较多出现在用了自定义的圆形图片控件或者CircleImageView之类的,解决方法如下:
(1)不设置占位图
(2)使用Glide自带的转换来加载圆形图片

Glide.with(this)     .load(url)     .asBitmap()     .centerCrop()     .override(300, 300)     .error(R.mipmap.delete)     .into(new BitmapImageViewTarget(imageView) {              @Override              protected void setResource(Bitmap resource) {              RoundedBitmapDrawable circularBitmapDrawable =                      RoundedBitmapDrawableFactory.create(context.getResources(), resource);              circularBitmapDrawable.setCircular(true);              imageView.setImageDrawable(circularBitmapDrawable);              }       });

(3) 使用bitmap加载到CircleImageView中

Glide.with(mContext)     .load(url)      .placeholder(R.drawable.loading_spinner)     .into(new SimpleTarget<Bitmap>(width, height) {        @Override         public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {            CircleImageView使用setImageBitmap(bitmap)         }     };

2.设置了占位图后,第一次加载的图片大小和占位图一样
比如我在XML里这么写

     <ImageView            android:id="@+id/normal_iv"            android:layout_width="150dp"            android:layout_height="200dp"            android:scaleType="fitCenter"/>

在Activity里这么写

Glide.with(mContext)                .load(Constant.IMAGE_URL)                .placeholder(R.mipmap.ic_zhanwei)                .into(normalIv);

占位图是一张正方形的图,要加载的是一张宽图,ScaleType用的是fitCenter,理论上讲加载出来的图片应该是居中等比例显示的,就像这样
这里写图片描述
但实际上第一次加载时,是这样
这里写图片描述
图片被拉伸到和占位图一样的大小, 只有加载过一次后,图片才能正常加载。这种情况比较多出现在特定宽高或者动态创建ImageView时,设置的占位图和实际加载的图片或ScaleType比例不同,解决办法是去除占位图,在ImageView中设置background当占位图。

3.You cannot start a load for a destroyed activity
当Glide.with()传的是Activity或者Fragment的Context时,比较容易出现这个报错。这是由于Activity已经destroy了,但是Glide依然在加载图片,结果就报错了。
比较常见的解决办法是传入ApplicationContext, 这样虽然不会出问题,但当Activity已经关闭时,还会继续加载,有点浪费内存了。 这个issue 提到说如果是在async task使用Glide加载时,最好还是传入ApplicationContext, 尽量避免新开线程去加载图片。

个人使用的方法有两个:
方法一: 项目一般都会写一个统一的图片加载工具,图片加载最后都通过统一的一个方法,当activity 销毁后,使用Glide加载会报错,那就可以在加载方法的最开始添加一个判断,如果当Activity已经销毁时,就return, 不进行加载,反之再进入加载代码,如下:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {            if (context instanceof Activity && ((Activity) context).isDestroyed()) {                return;            }        }

这样加了一个判断后,没有遇到过报错了,目前来看还是可行的。
方法二: 目前项目用到的方法是使用RequestManager来替代Glide.with, 也就是说,在统一的加载方法中定义的是RequestManager, 然后使用时传入Glide.with(context)。RequestManager可以同步Activity/Fragment的生命周期,当Activity销毁时,Glide的加载也会停止,使用起来也是很方便,代码如下:
统一的加载方法, LoadOption是我自己定义的加载选项,可以忽略:

  private void initLoadImage(RequestManager glide, Context context, String url, ImageView imageView, LoadOption option) {                glide.load(url)                        .error(R.mipmap.delete)                        .thumbnail(0.1f)                        .into(imageView);    }

使用时直接传入Glide.with(context)

initLoadImage(Glide.with(context), context, url, imageView, LOAD_ORIGIN);

也可以参考下这个问题。在我的Demo里也简单封装了一个Glide工具类,有问题的可以看看。

4.加载GIF特别慢或加载出错
偶尔需要加载GIF图片时,会出现加载很慢的情况,可以加上diskCacheStrategy(DiskCacheStrategy.SOURCE),这样可以很快加载出来。另外可以通过GlideDrawableImageViewTarget(ImageView view, int maxLoopCount)进行循环次数的控制。
加载GIF一般会加上asGif的方法,不加也是可以加载的,但如果加上这个方法后,图片却不是GIF,会加载出错。

三、Glide加载不同类型图片,如圆形,圆角,毛玻璃等
之前在加载圆形头像有说到可以在into的方法里new一个SimpleTarget或者BitmapImageViewTarget取得图片bitmap,最后自行处理,但对于链式结构的Glide加载代码而言,这么写看着有些冗杂。Glide也提供了bitmapTransform和transform的方法,可以自定义转换Transformation。
这里推荐一个强大的转换库Glide Transformations,支持圆形,圆角,毛玻璃,滤镜等等一系列加载转换,基本都是一行代码实现,可以满足绝大多数的需求了。
用法
直接在gradle里导入

compile 'jp.wasabeef:glide-transformations:2.0.2'

简单使用时

Glide.with(this).load(R.drawable.demo)        .bitmapTransform(new BlurTransformation(context))        .into((ImageView) findViewById(R.id.image));

混合使用:

Glide.with(this).load(R.drawable.demo)  .bitmapTransform(new BlurTransformation(context, 25), new CropCircleTransformation(context))  .into((ImageView) findViewById(R.id.image));

使用相当方便,具体可以到GitHub上看看。

暂时到这,如果有发现新的问题再继续补充。

0 0
原创粉丝点击