Glide 图片库原理(二)

作者: zcwfeng | 来源:发表于2021-01-06 00:05 被阅读0次

    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);
                }
    

    相关文章

      网友评论

        本文标题:Glide 图片库原理(二)

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