您的位置:首页 > 其它

图片加载框架Glide使用详解

2016-07-16 03:20 686 查看
最终我还是决定使用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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图片