1.Glide是什么?
Glide是Google在2014的IO大会发布一款图片处理框架,是目前android领域比较成熟的一款,也是Google官方推荐的图片处理框架,主要支持网络图片、二进制流、drawable资源、本地图片显示,还支持本地视频显示。
2. Glide 基本用法
1.在app级别下面配置gradle
dependencies {
implementation 'com.github.bumptech.glide:glide:4.11.0' //图片加载框架
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' //图片加载框架注解处理器
}
2.通过Glide类进行一个链式调用
Glide.with(getApplicationContext()).load(imageurl).into(imageview);
with()
在使用过程中尽量要传入Applicaiton、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
图片加载完成之前显示的占位图。
into()
一般传 ImageView 。
3. Glide原理
with是Glide类的一个静态方法,重载方法很多可以接收
Activity,Fragment,Context。
with方法里面,首先会调用RequestManagerRetriever的静态get方法得到RequestManagerRetriver对象。然后再调用该对象的get方法获取RequestManager对象。静态get方法中也有很多重载方法,主要分为传入Application参数和非Application参数,传入Application参数是最简单的情况,Glide只要持保和整个应用生命周期同步。
非Application参数不管是Activity,Fragment,最终都会向当前Activity传入一个隐藏的Fragment,因为Glide需要监控Activity的生命周期,Fragment依赖Activity生命周期并且是同步的,通过这个隐藏的Fragment就监听到Activity生命周期。
load方法,with方法返回的是一个RequestManager对象,所以load方法在RequestManager类中,load方法也有很多重载,支持本地图片,内存图片,网络图片,只看加载url的load方法。首先调用了fromString方法,再调用load方法,传入图片url,fromString方法里调用了loadGeneric方法,这个方法创建并返回了DrawableTypeRequest对象。
DrawableTypeRequest并没有load方法,load在DrawableTypeRequest的父类DrawableTypeRequestBuildle中。大部分操作都在这个类中,比如placeholder占位符,error,discacheStrategy等。
into方法是Glide图片加载流程中逻辑最为复杂的方法。
into方法在DrawableTypeRequestBuilder类中,里面调用了super.into方法,真正的实现在DrawableTypeRequestBuilder的父类GenericRequestBuilder中,这个类包括了网络请求,图片解析,图片解码,bitmap生成,缓存处理,图片压缩等大量逻辑操作,最后的最后才将图片展示出来。
总结:
Glide在加载绑定了Activity的生命周期。
在Activity内新建一个无UI的Fragment,这个特殊的Fragment持有一个Lifecycle。通过Lifecycle在Fragment关键生命周期通知RequestManger进行相关的操作。
在生命周期onStart时继续加载,onStop时暂停加载,onDestory是停止加载任务和清除操作。
4.Glide三级缓存
内存缓存:优先加载,速度最快
本地缓存:次优先加载,速度快
网络缓存:最后加载,速度慢,浪费流量
三级缓存策略,最实在的意义就是减少不必要的流量消耗,增加加载速度。
如今的 APP 网络交互似乎已经必不可少,通过网络获取图片再正常不过了。但是,每次启动应用都要从网络获取图片,或者是想重复浏览一些图片的时候,每次浏览都需要网络获取,消耗的流量就多了,在如今的流量资费来说,肯定会容易影响用户数量。
还有就是网络加载图片,有时候会加载很慢,影响了用户体验。
另外从开发角度来说,Bitmap 的创建非常消耗时间和内存,可能导致频繁GC。而使用缓存策略,会更加高效地加载 Bitmap,减少卡顿,从而减少读取时间。
而内存缓存的主要作用是防止应用重复将图片数据读取到内存当中,硬盘缓存则是防止应用重复从网络或其他地方重复下载和读取数据。
5.三级缓存的原理
首次加载的时候通过网络加载,获取图片,然后保存到内存和 SD 卡中。
之后运行 APP 时,优先访问内存中的图片缓存。
如果内存没有,则加载本地 SD 卡中的图片。
具体的缓存策略可以是这样的:内存作为一级缓存,本地作为二级缓存,网络加载为最后。其中,内存使用 LruCache ,其内部通过 LinkedhashMap 来持有外界缓存对象的强引用;对于本地缓存,使用 DiskLruCache。加载图片的时候,首先使用 LRU 方式进行寻找,找不到指定内容,按照三级缓存的方式,进行本地搜索,还没有就网络加载。
LruCache 采用最近最少使用算法,设定一个缓存大小,当缓存达到这个大小之后,会将最老的数据移除,避免图片占用内存过大导致OOM。
Glide缓存机制大致分为三层:Lru算法缓存、弱引用缓存、磁盘缓存。
读取的顺序是:Lru算法缓存、弱引用缓存、磁盘缓存
写入的顺序是:弱引用缓存、Lru算法缓存、磁盘缓存(不准确)
6.Glide优点(与Fresco相比)
Glide:
多种图片格式的缓存,适用于更多的内容表现形式(如Gif、WebP、缩略图、Video)
生命周期集成(根据Activity或者Fragment的生命周期管理图片加载请求)
高效处理Bitmap(bitmap的复用和主动回收,减少系统回收压力)
高效的缓存策略,灵活(Picasso只会缓存原始尺寸的图片,Glide缓存的是多种规格),加载速度快且内存开销小(默认Bitmap格式的不同,使得内存开销是Picasso的一半)
Fresco:
最大的优势在于5.0以下(最低2.3)的bitmap加载。在5.0以下系统,Fresco将图片放到一个特别的内存区域(Ashmem区)
大大减少OOM(在更底层的Native层对OOM进行处理,图片将不再占用App的内存)
适用于需要高性能加载大量图片的场景
对于一般App来说,Glide完全够用,而对于图片需求比较大的App,为了防止加载大量图片导致OOM,Fresco 会更合适一些。并不是说用Glide会导致OOM,Glide默认用的内存缓存是LruCache,内存不会一直往上涨。