图片加载框架Glide使用详解
Posted 逆水当行舟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图片加载框架Glide使用详解相关的知识,希望对你有一定的参考价值。
最终我还是决定使用Glide,作为我以后的主要图片加载框架。主要基于三点考虑
- 代码有人维护,不至于出现问题,项目组都搞不定的时候问题无法解决。(ImageLoader已没人维护了)
- 代码简洁,可读性很好。(Fresco是一个非常优秀的库,但是配置稍显麻烦,同时代码风格读起来有些生疏)
- 功能强大(400多k的包,包含很多功能,例如:像加载Gif图片就是Picasso做不到的)
但是,首要解决的就是,在Blog中提到的,图片常常加载失败。
打印错误日志与调试
我们看到仅仅是显示一张错误的图片,但是为什么会这样,日志里面没有任何输出。
监听器配置
Glide.with(getContext())
.load(url)
.listener(mRequestListener)//配置监听器
.placeholder(Drawables.sPlaceholderDrawable)
.error(Drawables.sErrorDrawable)
.into(mImageView);
打印日志
private RequestListener<String, GlideDrawable> mRequestListener = new RequestListener<String, GlideDrawable>()
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource)
//显示错误信息
Log.w(TAG, "onException: ", e);
//打印请求URL
Log.d(TAG, "onException: " + model);
//打印请求是否还在进行
Log.d(TAG, "onException: " + target.getRequest().isRunning());
return false;
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource)
return false;
;
这里的onException
捕获异常,如果返回true
表示我们自己处理掉了异常,false
表示交给Glide去处理,因为我们定义了.error()
那么就显示error里面的内容。
这里onResourceReady
表示是否准备资源显示,返回true
表示用户自己已经设置好资源,包括截取操作,动画操作之类的,准备好显示。false
表示交给Glide
如此修改后,看到日志终于打印出来了。查看日志,发现Glide本身自带的网络栈,在网络环境比较差的情况下(只是差,使用其他框架图片可以比较慢的显示出来)
/com.example.imageloadpk W/GlideHolder: onException:
java.lang.RuntimeException: java.net.SocketTimeoutException
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:162)
...
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:118)
Caused by: java.net.SocketTimeoutException
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:484)
at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
...
看到是SocketTimeoutException
错误,连接超时。但是发现Picasso没有这个错误,Picasso使用okHttp作为网络栈,好在Glide允许我们自己指定他的网络栈,马上动手修改。
替换掉自带的HttpClient
只需两步
Step1:
导入需要替换的HttpClient,可以选择Volley也可以选择OkHttp,我们使用Okhttp,在Module的build.gradle
文件中配置
dependencies
compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
compile 'com.squareup.okhttp3:okhttp:3.3.1'
or
compile 'com.github.bumptech.glide:volley-integration:1.4.0@aar'
compile 'com.mcxiaoke.volley:library:1.0.8'
这个版本具体选择多少,可以在https://github.com/bumptech/glide/wiki/Integration-Libraries这里查询到
Step2:
在androidMainfest.xml文件中写入
<meta-data
android:name="com.bumptech.glide.integration.okhttp3.OkHttpGlideModule"
android:value="GlideModule"/>
你可能会有和我一样的疑问,Glide可以通过在配置清单里面配置
能不能写几个meta-data标签,一个标签里面配置一点参数
经过测试,发现这样做也是可以的。但是如果是同一种配置信息,比如你集成了OkHttp,又写一个标签集成Volley,最后一个会把前面的覆盖掉。
修改缓存大小、位置、加载图片质量
和指定HttpClent为OkHttp一样,只不过我们需要配置一些信息在applyOptions()
函数里面
public class GlideConfigModule implements GlideModule
@Override
public void applyOptions(Context context, GlideBuilder builder)
// 指定位置在packageName/cache/glide_cache,大小为MAX_CACHE_DISK_SIZE的磁盘缓存
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "glide_cache", ConfigConstants.MAX_CACHE_DISK_SIZE));
//指定内存缓存大小
builder.setMemoryCache(new LruResourceCache(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
//全部的内存缓存用来作为图片缓存
builder.setBitmapPool(new LruBitmapPool(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);//和Picasso配置一样
@Override
public void registerComponents(Context context, Glide glide)
<meta-data
android:name="com.example.imageloadpk.adapter.config.GlideConfigModule"
android:value="GlideModule"/>
Glide缓存方式,可以作为其他用途
你们发现没有,一般的图片加载框架设置了磁盘缓存和内存缓存就行了,但是Glide还设置了一个图片缓存
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "glide_cache", ConfigConstants.MAX_CACHE_DISK_SIZE));
//指定内存缓存大小
builder.setMemoryCache(new LruResourceCache(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
//全部的内存缓存用来作为图片缓存
builder.setBitmapPool(new LruBitmapPool(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
最开始我在想,这不多此一举吗,内存缓存大小不就是图片缓存大小么。后面发现不是
图片缓存 <= 内存缓存
这里Glide不仅可以缓存图片,还可以缓存其他文件譬如视频之类,也就是说可以把他作为我们的缓存工具来使用,当然缓存方式还是使用LRU。这样我们就不必再去重新集成LruCache和DiskLruCache,再去申请空间,配置。直接可以复用Glide的。
使用加载动画
Glide提供淡如淡出
.crossFade()
使用Android系统提供,从左到右滑出加载动画
.animate(android.R.anim.slide_in_left)
自定义从小到大填充动画
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="@android:integer/config_longAnimTime"
android:fromXScale="0.1"
android:fromYScale="0.1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1"/>
</set>
.animate(R.anim.scale)
使用缓存也加载动画
但是,动画默认是在图片没有缓存的情况下才加载,想想也是合理的,如果图片已近下载到本地加载速度将会非常快,这个时候使用动画过渡反而碍事。要让从缓存中图片呈现也加载动画不能通过这种方式实现,可以用监听器来做。
private RequestListener<String, GlideBitmapDrawable> mAnimationRequestListener = new RequestListener<String, GlideBitmapDrawable>()
@Override
public boolean onException(Exception e, String model, Target<GlideBitmapDrawable> target, boolean isFirstResource)
return false;
@Override
public boolean onResourceReady(GlideBitmapDrawable resource, String model, Target<GlideBitmapDrawable> target, boolean isFromMemoryCache, boolean isFirstResource)
dissProgress();
if (isFromMemoryCache)
//如果是从缓存加载,设置动画效果
mIvShow.setAnimation(AnimationUtils.loadAnimation(mContext, R.anim.scale));
//返回true表示拦截不再传递,false表示事件会传递下去
return false;
;
指定大小
.override(600, 300)
不是说Glide可以根据,控件的大小自动测绘然后填充吗?
但是再有些情况下,譬如App的闪屏页面,还来不及测绘,就需要获取图片数据了。
而且,有些事后,我们可以使用Glide为工具,用这种方式对图片进行压缩裁剪。
不为ImageView类型加载
譬如加载的控件类型不是ImageView,是个自定义的布局。或者加载为Background的形式。
可以使用SimpleTarget
类型,这里指定他的大小为500*100,加载为背景图片。
.into(new SimpleTarget<Drawable>(500, 100)
@Override
public void onResourceReady(Drawable resource, GlideAnimation<? super Drawable> glideAnimation)
mBtnClear.setBackground(resource);
同理下载图片原理是一样
.into(new SimpleTarget<Bitmap>()
@Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation)
//toSave
Log.d(TAG, "onResourceReady: save successful");
);
请求优先级调整
Glide.with(mContext)
.load(Url.IMAGE_URL_TROCHILIDAE)
.priority(Priority.HIGH)
.into(mIvTonyRight);
优先级设置一览
public enum Priority
IMMEDIATE,
HIGH,
NORMAL,
LOW, priority,
代码下载地址:https://github.com/zhouruikevin/ImageLoadPK
以上是关于图片加载框架Glide使用详解的主要内容,如果未能解决你的问题,请参考以下文章
Android图片加载与缓存开源框架总结七部曲:Glide Picasso ImageLoader Fresco ASimpleCache等