Glide流程笔记

Glide

简单使用
Glide.with(Context)
.load(url)
.into(view);

框架都是从简单的思想发展出来的,只是用了一些特殊的方式来实现和扩展。

加载图片最简单的思想:

根据地址获取图片--> 按照显示区域放大或者缩小 --> 设置给ImageView。

Glide也是这样的,按照这个思路进行学习。

Glide.with(context)

根据context 和所在的线程,绑定生命周期。
如果是在主线程,且Context 可以定位到一个Activity,那么就创建一个没有view的frament放在Activity里,请求回绑定fragment的生命周期,也就是Activity的生命周期。
如果是子线程,或者Application的Context,那么就和Application绑定。

这一步会创建一个RequestManager。

asBitmap().apply(xxx).load(url).listener(xxx)

通过asBitmap 创建一个RequestBuilder,之后的操作相当与给RequestBuilder设置参数,顾名思义,最后会创建一个Request。

into(view)

关键的最后一步

1.根据imageView的scaleType和目标格式(asBitmap和asDrawable 还是asGif)来创建一个Target。

  1. 根据target和设置的RequestOption创建一个Request。如果和view之前的request相同,则回收现在的request,再执行一遍之前的request。

  2. 否则,使用requestManager的track方法执行request。不在运行时,则调用request.begin方法开始执行,一般创建的是SingleRequest。

  3. SingleReqeust的begin方法,先判断是否在运行,如果正在运行,则抛出异常。如果已经完成,则直接回掉onResourceReady。否则,设置当前状态为WAITING_FOR_SIZE,然后根据宽高,调用onSizeReady方法。

5.设置状态为RUNNING,根据宽高和各种请求参数等调用engine.load方法去加载。

6.Engine的load方法 回根据宽高等参数生成一个key,然后开始查找资源。

1)如果没有设置skipMemoryCache,则从memory中查找,如果找到了,则从memoryCache中移除,并且以弱引用的方式加入activeResource中。然后回掉onReasourceReady,结束。memoryCache会在每次释放一个View的内容时,如果可缓存将其加入。

2)没找到,则从activeResource中查找,找到了则返回并会掉OnResourceReady,否则删除这个弱引用。

3)依然没有找到,从job列表中查找是否有相同的请求,如果有,则在这个请求上再添加上自己的callback,否则则创建一个engineJob,一个decodeJob。并将engineJob加入job列表,然后通过start方法传入docodeJob进行执行。
其实主要任务时decodeJob进行的,engineJob只是一个回掉作用。。。

4) decodeJob会被engine执行,如果缓存策略时全部缓存。那么接下来的顺序如下。

glide将源数据分为两种:

Data:获取到的原始数据,原始图片。

Resource:Data转换后的图片。

比如原图1000*1000,目标区域是500*500,那么data是1000的图片,resource是500的。

1.第一步,如果当前缓存策略可以使用resource缓存,创建ResourceCahceGenerator查找resource缓存。

ResourceCacheGenerator 根据DiskLruCache查找磁盘缓存的File,找到的话,通过Registry查找可以处理File的ModelLoader列表。ModelLoader 是表示可以处理一类输入数据的一个处理器,Model就是指源数据类型(这里源数据是file)。 Glide默认有FileLoader。

遍历这些ModelLoader,创建LoadData对象,并使用该对象加载model(这里是File),会创建FileFetcher来load,并以当前的ResourceCacheGenerator作为回掉callback。 源码中打开文件有两种方式,一种是打开为InputStream,一种是ParcelFileDescriptor。

打开成功onDataReady失败则onLoadFailed。

ResourceGenerator又回回掉onDataFetcherReady,这里又重新回到DecodeJob。

DecodeJob保存这些数据(假如是InputStream),设置理由为DECODE_DATA然后回掉EngineJob 重新调度当前任务(reschedule)。

重新调度回再次执行DecodeJob的run方法,本次理由改变,最终会执行decodeFromRetrievedData。这里面根据当前的数据类型和资源类型,从registry中找到可以将该数据类型(InputStream)转换至目标资源类型(Bitmap、Drawable、GifDrawable)的加载器,并最终找到一个ResourceDecoder调用他的decode方法处理成目标资源对象(假如为Bitmap)。

重新回到DecodeJob,成功加载再到资源后,回掉callback的onResourceReady(engineJob),engineJob会通过handler切换到主线程并回调所有的callback(ResourceCallback,来自Engine,Engine的callback又来自与SingleRequest),SingleRequest中又会最终回调到我们设置的RequestListener,如果我们的RequestListener的onResourceReady没有返回Ready,就会调用Target的onResourceReady,这里回真正设置Bitmap或者Drawable给ImageView。

除了Glide默认的ResourceDecoder之外,还可以自定义ResourceDecoder。通过继承AppGlideModule,可以在registerComponenets中通过registry注册自己的方法。如下

   @Override
   public void registerComponents(Context context, Glide glide, Registry registry) {
       //意思是,注册一个可以将InputStream 转化为GifDrawble的BpgInputStreamDecoder到列表最前面的位置。
       // 注册一个将InputStream转为Bitmap的BpgBitmapDecoder 到列表最后的位置
       registry.prepend(InputStream.class, GifDrawable.class, new BpgInputStreamDecoder(context))
               .append(InputStream.class, Bitmap.class, new BpgBitmapDecoder());
   }

  

而自定义ResourceDecoder如下图


自定义ResourceDecoder.png

继承了ResourceDecoder,泛型为InputStream 和 Bitmap,表示这个ResourceDecoder是将InputStream转化为Bitmap。
重写handles方法:判断当前的ResourceDecoder是否可以处理这个source。

重写docode方法,根据width、height和options,将source转化为bitmap。

其他Generator的流程类似,从服务器获取的话多了请求和返回的流程。

整体流程如下图:

从红色的start处开始,之前的流程很好debug,就不加入了。

Glide请求流程.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,928评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,748评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,282评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,065评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,101评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,855评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,521评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,414评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,931评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,053评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,191评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,873评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,529评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,074评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,188评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,491评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,173评论 2 357

推荐阅读更多精彩内容