美文网首页
Glide解析学习记录

Glide解析学习记录

作者: 欧阳峰_oyf | 来源:发表于2019-08-21 16:51 被阅读0次

    Glide版本是3.7.0,默认加载图片格式RGB_565, 默认使用的是HttpURLConnection

    With

    RequestManager rm=Glide.with();

    首先,调用Glide.with()方法用于创建一个加载图片的实例。with()方法可以接收Context、Activity或者Fragment类型的参数。不管是在Activity还是Fragment中调用with()方法,都可以直接传this。我们可以获取当前应用程序的ApplicationContext,传入到with()方法当中。注意with()方法中传入的实例会决定Glide加载图片的生命周期,如果传入的是Activity或者Fragment的实例,那么当这个Activity或Fragment被销毁的时候,图片加载也会停止。如果传入的是ApplicationContext,那么只有当应用程序被杀掉的时候,图片加载才会停止。

    load

    load()方法,这个方法用于指定待加载的图片资源。Glide支持加载各种各样的图片资源,包括网络图片、本地图片、应用资源、二进制流、Uri对象等等

    into

    into()方法不仅仅是只能接收ImageView类型的参数,还支持很多更丰富的用法,不过那个属于高级技巧

    占位图

    placeholder-加载中占位图

    error -加载失败占位图

    图片格式性质

    Glide会去帮我们自动进行图片格式的判断,然后显示相应的格式

    asBitmap  -只显示图片

    asGif -加载gif图片(如果传入静态图片会进入加载失败)

    图片大小

    override(w,h)-加载指定大小的图片

    with方法源码

    RequestManager得获取源码

    RequestManagerRetriever 的get方法 分为传入Application类型的参数,和传入非Application类型的参数。

    Application ----getApplicationManager()方法来获取一个RequestManager对象

    非Application----流程都是一样的,那就是会向当前的Activity当中添加一个隐藏的Fragment,因为Glide并没有办法知道Activity的生命周期 ,Fragment的生命周期和Activity是同步的,如果Activity被销毁了,Fragment是可以监听到的,所以。。。。

    注意--在非主线程当中使用的Glide,那么不管你是传入的Activity还是Fragment,都会被强制当成Application来处理 (Util.isOnMainThread()方法判断)

    一个with()方法的源码还是比较好理解的。其实就是为了得到一个RequestManager对象而已,然后Glide会根据我们传入with()方法的参数来确定图片加载的生命周期

    Load方法源码

    DrawableTypeRequest<ModelType>的获取,通过load(..)

    load(String)--formString()--loadGeneric(String.class)返回StreamStringLoader实现了ModelLoaderload(Uri)--formUri()-- loadGeneric(Uri.class)返回 StreamUriLoader实现了 ModelLoader

    .....

    new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context, glide, requestTracker, lifecycle, optionsApplier);

    DrawableTypeRequest的作用

    主要是asGif或者asBitmap或者默认的

    然后父类中就有那些placeholder()、error()、diskCacheStrategy()等等属性的设置

    into方法源码

    只有一句super.into(view)。那么很显然,into()方法的具体逻辑都是在DrawableRequestBuilder的父类GenericRequestBuilder当中了

    逻辑----先判断线程是否是主线程----判断是由isTransformationSet并且图片的scaleType是否改变------最后一行代码先是调用了glide.buildImageViewTarget()方法,这个方法会构建出一个Target对象,Target对象则是用来最终展示图片用的 -----在buildTarget()方法中会根据传入的class参数来构建不同的Target对象。那如果你要分析这个class参数是从哪儿传过来的,简单起见我直接帮大家梳理清楚。这个class参数其实基本上只有两种情况,如果你在使用Glide加载图片的时候调用了asBitmap()方法,那么这里就会构建出BitmapImageViewTarget对象

    Request request=buildRequest(target);

     target.setRequest(request); 

    lifecycle.addListener(target); 

    requestTracker.runRequest(request);  

    最后是调用Request request=GenericRequest.obtain(n多参数-error-placeholder-overrideWidth等)

    配置好参数后开始执行GenericRequest 的begin()里面判断model == null进入 onException(null);也就是加载失败的占位图然后override方法是否修改图片,最终都会进入onSizeReady然后配置一大堆,最终去读取inputstream,decodeStream()方法中会先从流中读取2个字节的数据,来判断这张图是GIF图还是普通的静图-----如果是GIF图就调用decodeGifWrapper()方法来进行解码,如果是普通的静图就用调用decodeBitmapWrapper()方法来进行解码。 然后调用了Downsampler的decode()方法返回一个bitmap,在decode方法中处理了很多的逻辑,包括对图片的压缩,甚至还有旋转、圆角等逻辑处理,

    GlideDrawableImageViewTarget的setResource()方法,没错,调用的view.setImageDrawable()方法,而这个view就是ImageView。代码执行到这里,图片终于也就显示出来了。

    Glide的缓存

    内存缓存--LRU缓存及glide内部的弱引用缓存办法

    skipMemoryCache(boolean)  ---是否跳过缓存

    LruCache算法(Least Recently Used),也叫近期最少使用算法。它的主要算法原理就是把最近使用的对象用强引用存储在LinkedHashMap中,并且把最近最少使用的对象在缓存值达到预设定值之前从内存中移除。Glide还结合了一种弱引用的机制,共同完成了内存缓存功能

    Gilde是单例模式通过GlideBuilder的createGlide()方法来创建的 ,在里面 new LruResourceCache

    Glide的图片加载过程中会调用两个方法来获取内存缓存,loadFromCache()(备注-优先调用这个)和loadFromActiveResources()。这两个方法中一个使用的就是LruCache算法,另一个使用的就是弱引用

    注意点从LruResourceCache中获取到缓存图片之后会将它从缓存中移除,然后这个缓存图片存储到activeResources当中。activeResources就是一个弱引用的HashMap,用来缓存正在使用中的图片,loadFromActiveResources()方法就是从activeResources这个HashMap当中取值的。使用activeResources来缓存正在使用中的图片,可以保护这些图片不会被LruCache算法回收掉。

    EngineResource是用一个acquired变量用来记录图片被引用的次数,调用acquire()方法会让变量加1,调用release()方法会让变量减1

    当acquired变量大于0的时候,说明图片正在使用中,也就应该放到activeResources弱引用缓存当中。而经过release()之后,如果acquired变量等于0了,说明图片已经不再被使用了,那么此时会调用listener的onResourceReleased()方法来释放资源,这个listener就是Engine对象,我们来看下它的onResourceReleased()方法 ---首先会将缓存图片从activeResources中移除,然后再将它put到LruResourceCache当中。这样也就实现了正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能

    diskCacheStrategy---硬盘缓存

    DiskCacheStrategy.NONE: 表示不缓存任何内容。

    DiskCacheStrategy.SOURCE: 表示只缓存原始图片。

    DiskCacheStrategy.RESULT: 表示只缓存转换过后的图片(默认选项)。

    DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片

    DiskCacheStrategy.AUTOMATIC: 表示让Glide根据图片资源智能地选择使用哪一种缓存策略(默认选项)。 glide4中新增加的

    硬盘缓存的实现也是使用的LruCache算法

    Glide的缓存Key是由10个参数共同组成的,包括图片的width、height等等

    缓存的原始图片只使用了id和signature这两个参数来构成缓存Key。而signature参数绝大多数情况下都是用不到的,因此基本上可以说就是由id(也就是图片url)来决定的Original缓存Key。

    原始图片写入磁盘在DecodeJob类中的decodeFromSourceData方法中缓存磁盘数据cacheAndDecodeSourceData();

    转换后的图片写入磁盘在transformEncodeAndTranscode后使用writeTransformedToCache写入磁盘

    缓存中特殊情况,图片中使用了token参数

    GlideUrl类的构造函数接收两种类型的参数,一种是url字符串,一种是URL对象。然后getCacheKey()方法中的判断逻辑非常简单,如果传入的是url字符串,那么就直接返回这个字符串本身,如果传入的是URL对象,那么就返回这个对象toString()后的结果。

    getCacheKey()方法中的逻辑太直白了,直接就是将图片的url地址进行返回来作为缓存Key的

    重写了getCacheKey()方法,在里面加入了一段逻辑用于将图片url地址中token参数的这一部分移除掉。这样getCacheKey()方法得到的就是一个没有token参数的url地址,从而不管token怎么变化,最终Glide的缓存Key都是固定不变的了

    Glide.with(this) .load(new MyGlideUrl(url)) .into(imageView);

    Glide的预加载

    preload()方法

    方法一 因为into()方法中除了传入ImageView之后还可以传入Target对象,如果我们在Target对象的onResourceReady()方法中做一个空实现,也就是不做任何逻辑处理,那么图片自然也就显示不出来了,而Glide的缓存机制却仍然还会正常工作(ViewTarget ,SimpleTarget)

    方法二 Glide专门给我们提供    了预加载的接口,也就是preload()方法,我们只需要直接使用就可以了。

    Glide.with(this) .load(url) .diskCacheStrategy(DiskCacheStrategy.SOURCE) .preload();

    downloadOnly==glide4中的submit

    和preload()方法类似,downloadOnly()方法也是可以替换into()方法的

    downloadOnly()方法表示只会下载图片,而不会对图片进行加载。当图片下载完成之后,我们可以得到图片的存储路径,以便后续进行操作

    downloadOnly(int width, int height)方法必须要用在子线程当中

    注意事项,当使用downloadOnly下载好的图片后,如需要使用必须使用将硬盘缓存策略指定成DiskCacheStrategy.SOURCE或者DiskCacheStrategy.ALL,否则Glide将无法使用我们刚才下载好的图片缓存文件。 Glide.with(this) .load(url) .diskCacheStrategy(DiskCacheStrategy.SOURCE) .into(imageView);

    Listener()方法 回调监听

    into()方法或者preload方法之前串接了一个listener()方法,然后实现了一个RequestListener的实例。其中RequestListener需要实现两个方法,一个onResourceReady()方法,一个onException()方法。

    图片的变换使用Transform

    https://github.com/wasabeef/glide-transformations   很多图片变化,圆角,长方形,五角星,等等

    替换位okhttp

    1.新建OkHttpFetcher实现DataFetcher<InputStream>

    2.新建OkHttpGlideUrlLoader实现ModelLoader<GlideUrl, InputStream>,在内部创建OkHttpClient,配置好参数,并且引用OkHttpFetcher

    3.创建MyGlideModule实现GlideModule,在里面注册OkHttpGlideUrlLoader;

    4.AndroidManifest.xml文件当中配置MyGlideModule

    下载监听

    1.添加拦截器

    2.在拦截器中重新替换ProgressResponseBody,生成新的response,在ProgressResponseBody计算下载进度,并且回调出去

    Glide4

    主要的配置参数移到 RequestOptions中

    ImageView.ScaleType / android:scaleType值的意义区别:

    CENTER /center按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示

    CENTER_CROP / centerCrop按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)

    CENTER_INSIDE / centerInside将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽

    FIT_CENTER / fitCenter把图片按比例扩大/缩小到View的宽度,居中显示

    FIT_END / fitEnd把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置

    FIT_START / fitStart把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置

    FIT_XY / fitXY把图片�不按比例扩大/缩小到View的大小显示

    MATRIX / matrix用矩阵来绘制,动态缩小放大图片来显示。

    相关文章

      网友评论

          本文标题:Glide解析学习记录

          本文链接:https://www.haomeiwen.com/subject/soybsctx.html