实用干货知识图谱每天进步一点点

Glide 图片库原理(二)

2021-01-06  本文已影响0人  zcwfeng

Glide 吐槽

源码太多了,状态机对于阅读源码来说是个苦力活,而且必须借助工具完成,推荐脑图

简化一个整个流程图

Glide整体简化图.png

with, load ,into

into 代码巨大,先上流程图

Glide.width 流程图

Gilde_with.png

into 流程图

Glide_into .png
由于代码流程太多,所以建议下载图片放大看细节。

或者跟着脑图走--->Github docs 放在vscode 插件中查看

分析源码思路,

第一大步:只管主线 简单的走通 不要管支线
第二大步:重点在主线,稍微瞄一眼支线
第三大步:稍微分析支线,回顾主线
第四大步:分析支线细节,回顾主线
第五大步:分析支线细节,来寻找答案

0.项目中大量的使用了Glide,偶尔会出现内存溢出问题,请说说大概是什么原因?
答:尽量在with的时候,传入有生命周期的作用域(非Application作用域),尽量避免使用了Application作用域,因为Application作用域不会对页面绑定生命周期机制,就回收不及时释放操作等....

1.使用Glide为什么要加入网络权限? <uses-permission android:name="android.permission.INTERNET" />
答:等待队列/运行队列 执行Request ---> 活动缓存 --->内存缓存 ---> jobs.get检测执行的任务有没有执行完成 ---> HttpUrlFetcher.HttpURLConnection

2.使用Glide时,with函数在子线程中,会有什么问题?
答:子线程,不会去添加 生命周期机制, 主线程才会添加 空白的Fragment 去监听 Activity Fragment 的变化。

3.使用Glide时,with函数传入Application后,Glide内部会怎么处理?
答:在MainActivity中,MainActivity销毁了,并会让Glide生命周期机制处理回收,只有在整个APP应用都没有的时候,跟随着销毁(上节课 ApplicationLIfecycle add onStart onDestroy 什么事情都没有做)。

4.Glide源码里面的缓存,为什么要有 活动缓存 还需要 有内存缓存?
答:
因为LRU内存缓存添加满的时候,刚好访问最少使用那个A,如果LRU在添加数据,那么就会移除A,但是界面正在用A,那么就会导致崩溃。为了解决这种问题,所以添加了活动缓存。
把正在使用的放在活动缓存中,并且是非LRU的缓存。

分析步骤

第一步:【with】
  public RequestManager get(@NonNull FragmentActivity activity) {
    if (Util.isOnBackgroundThread()) {
      // Application 作用域
    } else {
      // 非Application 作用域
    }
  }

第二步:【load】
最终返回:RequestBuilder

第三步:【into】  看源码的思路,如果遇到接口怎么办? 前面必须 埋下伏笔

1.  ImageViewTarget(显示图片) 无论走多远多远,最终一定回到这里ImageViewTarget  埋下伏笔
    return into(
              glideContext.buildImageViewTarget(view, transcodeClass),  ImageViewTarget
          );

2.  Request request = new SingleRequest 埋下伏笔

3.  SingleRequest   public void begin() {...}


4.       if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
            onSizeReady(overrideWidth, overrideHeight); 用户设置 宽和高
          } else {
            target.getSize(this); 用户没有设置 宽和高  再次测量 -----> onSizeReady
          }

5.        memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);  活动缓存 内存缓存
          if (memoryResource == null) {
              缓存没有
          }
          cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE); 命中缓存 回调去显示了


6.        EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache); 查找有没有正在运行的任务


7.        EngineJob线程池大管家  DecodeJob执行的任务

8.        currentGenerator = getNextGenerator();  SourceGenerator 埋下伏笔

9.        SourceGenerator  分析   LoadData<Data> buildLoadData 没有埋下伏笔   Glide预习资料(构造函数 注册机)
          .append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())  Glide 注册机 埋下了伏笔

          List<LoadData<?>> getLoadData() == HttpGlideUrlLoader {目标HttpUrlFetcher}

          最终返回:HttpUrlFetcher  终于找到了 网络访问的地方 HttpUrlConn 来得到 InputStream

10        public Resource<Transcode> decode(
          {
              // InputStream  ---> Bitmap  == decoded
              Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
              Resource<ResourceType> transformed = callback.onResourceDecoded(decoded); // 回调回去
              return transcoder.transcode(transformed, options);
            }
上一篇下一篇

猜你喜欢

热点阅读