1.Glide是什么?
Glide是Google在2014的IO大会发布一款图片处理框架,是目前android领域比较成熟的一款,也是Google官方推荐的图片处理框架,主要支持网络图片、二进制流、drawable资源、本地图片显示,还支持本地视频显示。
2.Glide基本功能使用
- 在app级别下面配置gradle
1 | dependencies { |
- 使用起来
通过Glide类进行一个链式调用,下面代码显示了一张网络图片。
with支持传入一下对象,我们在使用过程中尽量要传入activity、fragment因为glide会依赖它们的生命周期,如果onPaush时候,Glide就会暂停加载,重新onResume之后,又会继续加载。
load() 支持网络图片、二进制流、drawable资源、本地图片的传入。
crossFade 这是开启显示淡入淡出的动画
override 如果获取的网络图片过大,我们通过它进行一个大小的裁剪,传入width和height参数进行宽高裁剪。
diskCacheStrategy 磁盘缓存的设置,默认Glide会开启的。
DiskCacheStrategy.NONE 什么都不缓存
DiskCacheStrategy.SOURCE 只缓存全尺寸图
DiskCacheStrategy.RESULT 只缓存最终的加载图
DiskCacheStrategy.ALL 缓存所有版本图(默认行为)
Glide 不仅缓存了全尺寸的图,还会根据 ImageView 大小所生成的图也会缓存起来。比如,请求一个 800x600 的图加载到一个 400x300 的 ImageView 中,Glide默认会将这原图还有加载到 ImageView 中的 400x300 的图也会缓存起来。
- error 这里的设置是当加载图片出现错误时,显示的图片。
- placeholder 图片加载完成之前显示的占位图。
1
2
3
4
5
6
7
8
9
10
11
12
String url = "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2912495429,3557331556&fm=27&gp=0.jpg";
Glide
.with(this)
.load(url)
.crossFade()
.override(200, 200)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.error(R.mipmap.active_user_default_icon)
.placeholder(R.mipmap.ic_album_image_source_pick)
.into(img);
获取Glide请求完成的Bitmap
通过前面这种方式我们能很轻松的显示一张,图片到ImgeView上。但是我们有时候想获取加载完成后的Bitmap怎么办呢,可以通过SimpleTarget来获取。
1 | //SimpleTarget 获取bitmap,定义siez |
我们定义了一个SimpleTarget类,里面有一个onResourceReady方法的回调,会返回加载完成的Bitmap对象,into传入这个SimpleTarget对象。
自定义控件使用Glide显示Image
有时候我们自定义的控件也需要显示Imaeg,但是这个控件不是Image类或者子类,那么前面这种方法就会不使用了,我们可以通过ViewTarget来实现这个逻辑。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public class MyImageView extends FrameLayout {
private ImageView mImageView;
public MyImageView(@NonNull Context context) {
super(context);
}
public MyImageView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyImageView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mImageView = new ImageView(getContext());
addView(mImageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
public void setImage(Drawable drawable) {
mImageView.setImageDrawable(drawable);
}
}
1 | MyImageView img3; |
通过定义一个ViewTarget传入了二个泛型类,一个是MyImageView,一个是GlideDrawable,传入了img3。通过onResourceReady的回调我们可以对自定义控件进行图片显示了。
3.Glide原理了解?
Glide的with、load、into虽然只有三个方法调用但是内部的逻辑是很复杂的,成吨的代码这里我只做一个大概了解。首先with方法会构造一个单例的RequestManager对象。
with方法1
2
3
4public static RequestManager with(FragmentActivity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
1 | public static RequestManagerRetriever get() { |
可以看出来我们一个程序生命周期内只有一个RequestManager对象,工程师在设计的时候很考虑到性能的问题。
load方法
1 | public DrawableTypeRequest<String> load(String string) { |
接着通过RequestManage对象的load方法返回一个DrawableTypeRequest类,它是一个DrawableRequestBuilder的一个子类,通过类名可以看出来主要作用是主要是构建请求中的一些参数用的,比如我们之前写的 override、error、placeholder、diskCacheStrategy这些辅助方法的设置。
into方法
最后的一个方法也是最复杂的一个,是真正请求网络请求的地方。
1 | public Target<GlideDrawable> into(ImageView view) { |
1 | public Target<TranscodeType> into(ImageView view) { |
1 | @SuppressWarnings("unchecked") |
into接收一个ViewTeger,
into的调用
1 |
|
1 | public void runRequest(Request request) { |
runRequest方法来控制请求的队列,如果当前视图状态是Paused状态就会把request添加到等待请求的队列,如果不是则直接执行。里面会有一个HttpUrlFetcher来执行前面封装好的网络请求
4.Glide是如何缓存的?
glide缓存主要分为
- 内存缓存
内存缓存主要是防止同样的图片重复读取到内存中来,解约JVM的内存空间
glide的内存缓存机制是使用LruCache算法实现,首先需要会需要一个key,这个key是通过url+构建请求时候的参数决定的。keyFactory.buildKey的代码就是生成Key的逻辑。glide内存缓存会调用二个方法来获取缓存。
loadFromCache
使用LruCacheloadFromActiveResources
使用弱引用
内存缓存的逻辑就是,先会在loadFromCache中去取缓存,这个是一个LruCaChe算啊实现的,如果取到了值就会把它存入一个弱引用中。这样的防止被LruCache算法回收掉,如果LruCache没有取到就会去loadFromActiveResources方法里面取。
如果都没有那就会开启子线程去网络请求图片。
1 | public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher, |
- 磁盘缓存
磁盘缓存主要是防止同一张网络图片,重复从网络中读取和下载,磁盘缓存也是使用LruCache算法实现的。
磁盘缓存有一个逻辑,当需要去加载一张图片的时候,Glide默认不会显示原始图片,而是会对图片进行压缩转换。经过这些转换操作之后才会把,图片显示出来,磁盘缓存默认就是缓存转换后的图片。