什么是Glide
一个高效、开源、Android设备上的媒体管理框架,它遵循BSD、MIT以及Apache 2.0协议发布。Glide具有获取、解码和展示视频剧照、图片、动画等功能,它还有灵活的API,这些API使开发者能够将Glide应用在几乎任何网络协议栈里。
Glide特点
- 使用简单
- 可配置度高,自适应程度高
- 支持常见图片格式 Jpg png gif webp
- 支持多种数据源 网络、本地、资源、Assets 等
- 高效缓存策略 支持Memory和Disk图片缓存 默认Bitmap格式采用RGB_565内存使用至少减少一半
- 生命周期集成 根据Activity/Fragment生命周期自动管理请求
- 高效处理Bitmap 使用Bitmap Pool使Bitmap复用,主动调用recycle回收需要回收的Bitmap,减小系统回收压力
Glide的简单使用
- 在
build.gradle
中添加下面这行代码
compile 'com.github.bumptech.glide:glide:3.7.0'
设置绑定生命周期
Glide.with(Context context);// 绑定Context
Glide.with(Activity activity);// 绑定Activity
Glide.with(FragmentActivity activity);// 绑定FragmentActivity
Glide.with(Fragment fragment);// 绑定Fragment
Glide 要求最少三个参数
- with();
- load(String imageUrl);//这里可以指定哪个图片应该被加载,同上它会是一个字符串的形式表示网络图片的URL
- into(ImageView targetImageView)//图片会显示到对应的ImageView中
例子
ImageView imageView = (ImageView) findViewById(R.id.imageView); String imageUrl= "http://i.imgur.com/DvpvklR.png"; Glide .with(context) .load(imageUrl) .into(imageView);
加载
- 从资源中加载
从Android资源中加载,使用一个资源id(int
),来替换之前使用字符串去指明一个网络URL的情况
int resourceId = R.mipmap.ic_launcher;
Glide
.with(context)
.load(resourceId)
.into(imageViewResource);
- 从文件中加载
//这个文件可能不存在于你的设备中。然而你可以用任何文件路径,去指定一个图片路径。
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Running.jpg");
Glide
.with(context)
.load(file)
.into(imageViewFile);
- 从Uri中加载
//这可能是任何 Uri。为了演示的目的我们只是用一个 launcher icon 去创建了一个 Uri
Uri uri = resourceIdToUri(context, R.mipmap.future_studio_launcher);
Glide
.with(context)
.load(uri)
.into(imageViewUri);
一个小助手功能:简单的从资源 id 转换成 Uri。
public static final String ANDROID_RESOURCE = "android.resource://";
public static final String FOREWARD_SLASH = "/";
private static Uri resourceIdToUri(Context context, int resourceId) {
return Uri.parse(ANDROID_RESOURCE + context.getPackageName() + FOREWARD_SLASH + resourceId);
}
- 从文件中加载
设置加载中以及加载失败图片
Glide.with(this).load(imageUrl).placeholder(R.mipmap.ic_launcher).error(R.mipmap.ic_launcher).into(imageView);
.placeholer()
:Glide将会显示它作为一个占位符,直到你的实际图片准备好
.error()
:Glide给我们一个选项去获取一个错误的回调并采取合适的行动
placeholer()接受的参数不能设置一个网络url作为占位符 因为会被请求加载,所以必须是App和drawable能保证可用和可访问的。
load()
方法的参数,Glide 接受所有值。这可能不是可加载的(没有网络连接,服务器宕机…),删除了或者不能访问
error()接受的参数只能是已经初始化的drawable对象或者指明它的资源(R.drawable.<drawable-keyword>
)
如果定义的load()
值的图片不能被加载出来,Glide会显示.error()
内的参数所代表的图片作为替换
设置加载动画
高于3.6.1
默认激活了一个淡入淡出动画
- 如果强制Glide显示一个淡入淡出动画,必须调用另外一个方法
.crossFade()
.crossFade(int duration)
:动画默认的持续时间是300毫秒,想要去减慢(或加快)动画,随时可以传入一个毫秒的时间给这个方法
- 想直接显示图片而没有任何淡入淡出效果
- 使用
.dontAnimate()
- 使用
- 例子
Glide.with(this).load(imageUrl).animate(R.anim.item_alpha_in).into(iamgeView)
R.anim.item_alpha_in
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="500"
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
</set>
图片重设大小和缩放
.override(horizontalSize,verticalSize)
Glide.with(this).load(imageUrl).override(800, 800).into(imageView);
.CenterCrop()
CenterCrop()
是一个裁剪技术,即缩放图像让它填充到 ImageView
界限内并且侧键额外的部分。ImageView
可能会完全填充,但图像可能不会完整显示。
.FitCenter()
fitCenter()
是裁剪技术,即缩放图像让图像都测量出来等于或小于 ImageView
的边界范围。该图像将会完全显示,但可能不会填满整个 ImageView
。
显示Gif和Video
- 显示Gif
Glide.with(this).load(imageUrl).asBitmap().into(imageView);//显示gif静态图片
Glide.with(this).load(imageUrl).asGif().into(imageView);//显示gif动态图片
- 同样可以使用
.placeholder()
.error()
这些方法 - 如果加载的图片不是gif,则
.asGif()
会报错, 当然,asGif()不写也是可以正常加载的。
缓存
- 内存缓存
- 设置跳过内存缓存:
Glide.with(this).load(imageUrl).skipMemoryCache(true).into(imageView);
- 这意味着Glide将不会把这张图片放到内存缓存中去,但是仍然利用磁盘缓存来避免重复的网络请求
- Glide将会默认将所有的图片资源放到内存缓存中去,因此不用指明
.skipMemoryCache(false)
提示:注意一个事实,对于相同的 URL ,如果你的初始请求没调用 .skipMemoryCache(true) 方法,你后来又调用了 .skipMemoryCache(true) 这个方法,这个资源将会在内存中获取缓存。当你想要去调整缓存行为时,确保对同一个资源调用的一致性
- 设置跳过内存缓存:
- 使用
.diskCacheStrategy()
改变磁盘缓存的行为
Glide.with(this).load(imageUrl).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView);
.diskCacheStrategy(DiskCacheStrategy.XXX)
内参数
- ALL:缓存源资源和转换后的资源(默认行为)
- NONE:不作任何磁盘缓存
- SOURCE:缓存源资源(仅仅只缓存原来的全分辨率的图像)
- RESULT:缓存转换后的资源(仅仅缓存最终的图像)
缓存的动态清理
Glide.get(this).clearDiskCache();//清理磁盘缓存 需要在子线程中执行
Glide.get(this).clearMemory();//清理内存缓存 可以在UI主线程中进行
图片请求的优先级
- 采用
.priority()
- 例子:
Glide.with(this).load(imageUrl).priority(Priority.NORMAL).into(imageView);
.priority()
内部参数,下面所列出是递增的顺序
- Priority.LOW
- Priority.NORMAL
- Priority.HIGH
- Priority.IMMEDIATE
优先级并不是完全严格遵守的。Glide 将会用他们作为一个准则,并尽可能的处理这些请求,但是它不能保证所有的图片都会按照所要求的顺序加载。
缩略图的使用
- 采用
.thumbnail(0.1f)
- 参数是一个
float
作为其大小的倍数 - 例子:
Glide.with(this).load(imageUrl).thumbnail(0.1f).into(imageView);
回调:SimpleTarget 和 ViewTarget 用于自定义视图类
Glide.with(this).load(imageUrl).centerCrop().into(new SimpleTarget<GlideDrawable>() {
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
imageView.setImageDrawable(resource);
}
});
从技术上来说,Java/Android 会允许你在 .into() 方法中去声明 target 的匿名内部类。然而,这大大增加了这样一个可能性:即在 Glide 做完图片请求之前, Android 垃圾回收移除了这个匿名内部类对象。最终这可能会导致一个情况,当图像加载完成了,但是回调再也不会被调用。所请确保你所声明的回调对象是作为一个字段对象的,这样你就可以保护它避免被邪恶的 Android 垃圾回收机制回收 ;-)
如果你的 target 是独立于应用的 activity 生命周期。这里的解决方案是用 application 的 context: .with(context.getApplicationContext))。当应用资深完全停止时,Glide 才会杀死这个图片请求。如果你的请求需要在 activity 生命周期之外去做时,才用.with(context.getApplicationContext))
这样的代码。
- ViewTarget===>看这里
设置监听请求接口
- 例子1:
Glide.with(this).load(imageUrl).listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
//imageView.setImageDrawable(resource);
return false;
}
}).into(imageView);
- 例子2:
- 创建一个监听作为一个字段对象去避免垃圾回收(注:之前说过不要用匿名内部类的形式):
private RequestListener<String, GlideDrawable> requestListener = new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
// todo log exception
// important to return false so the error placeholder can be placed
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
return false;
}
};
在onException
方法中, 你可以捕获错误,并且你可以决定要做什么,比如,打个 log。重要的是如果 Glide 要在后续处理的话,如显示一个错误的占位符等情况的话,你需要返回了 false 在onException
方法中。
* 接下来
Glide
.with( context )
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.listener( requestListener )
.error( R.drawable.cupcake )
.into( imageViewPlaceholder );
要使日志工作正常的话,.error()
并不是必须的。然而,如果你在监听的onException
中返回false
的话,R.drawable.cupcake
只是显示出来而已。
设置动态转换
如果你只是想要对图片(不是 Gif 和 video)做常规的 bitmap 转换,我们推荐你使用抽象类 BitmapTransformation。
* 我们用这样的框架
public class BlurTransformation extends BitmapTransformation {
public BlurTransformation(Context context) {
super( context );
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
return null; // todo
}
@Override
public String getId() {
return null; // todo
}
}
getId()
方法描述了这个转换的唯一标识符
- 单个转换应用
Glide
.with( context )
.load( eatFoodyImages[0] )
.transform( new BlurTransformation( context ) )
//.bitmapTransform( new BlurTransformation( context ) ) // this would work too!
.into( imageView1 );
.transform()
可以使用任何转换,无论它是否是用于图像还是 Gif。
.bitmapTransform()
,它只能用于 bitmap 的转换。
- 运用多种转换
Glide
.with( context )
.load( eatFoodyImages[1] )
.transform( new GreyscaleTransformation( context ), new BlurTransformation( context ) )
.into( imageView2 );
把一个图像设置了灰度,然后做了模糊,Glide自动执行了两个转换
提示:当你用了转换后你就不能使用 .centerCrop() 或 .fitCenter() 了。
- Glide的转换集合===>可以看下这个库:glide-transformations
- 同步这个库后
Glide
.with( context )
.load( eatFoodyImages[2] )
.bitmapTransform( new jp.wasabeef.glide.transformations.BlurTransformation( context, 25, 2 ) )
.into( imageView3 );
如何旋转图像
- 同步这个库后
加载图片到通知栏和应用小部件中
用 animate() 自定义动画
Glide Module系列
- 集成网络栈
- 用 Module 自定义 Glide
- Module 实例:接受自签名证书的 HTTPS
- Module 实例:自定义缓存
- Module 实例:用自定义尺寸优化加载的图片
- 动态使用 Model Loader