美文网首页
开源框架_01Glide

开源框架_01Glide

作者: 冉桓彬 | 来源:发表于2018-03-20 23:29 被阅读6次
    参考文章 :
    Glide基本用法 :
    Glide.with(Context).load(ImgResource).into(ImageView);
    
    一、Glide.with :
    1.1 Glide.with :
    Glide.with
    • 1、全局创建一个单例的Glide和GlideBuilder, //30L处在GlideBuilder内部初始化Glide;
    • 2、下文1.2的分析可知, GlideBuilder.build在初始化Glide的同时, 顺带初始化了一大批与下载相关的下载机制, 缓存机制相关的工具类;
    • 3、初始化RequestManagerRetriever之后, 在//6L处通过get持有Context的引用;
    • 4、由下文1.4 ~ 1.5可知, 通过如果在主线程中调用Glide.with并且传入非ApplicationContext, 则会获取当前Context关联的Activity, 然后往Activity中插入一个Fragment以监听Activity生命周期, 当Activity生命周期发生变化时, 通过RequestManagerFragment内部的RequestManager去控制当前图片加载状态;
    1.2 GlideBuilder.build :
    GlideBuilder.build
    • 1、初始化Glide时创建一大批下载机制, 缓存机制相关的工具类;
    1.3 Glide.getRequestManagerRetriever :
    Glide.getRequestManagerRetriever
    • 1、返回在1.2中创建的RequestManagerRetriever对象;
    1.4 RequestManagerRetriever.get :
    RequestManagerRetriever.get
    • 1、如果我们在非UI线程调用Glide.with操作或者我们在主线程中调用Glide, 但是传入的为ApplicationContext, 直接跳转至//12L;
    • 2、如果我们在UI线程中调用Glide.with并且传入的Context属于FragmentActivity/Activity/ContextWrapper时, 跳转至//3L内部;
    1.5 RequestManagerRetriever.get(Activity) :
    RequestManagerRetriever.get(Activity)
    • 1、如果传入的为Activity, 则为Activity创建一个RequestManagerFragment, 然后便通过RequestManagerFragment监听Activity的生命周期;
    • 2、//17L ~ //19L 完成RequestManagerFragment持有RequestManager实例的操作, 当Activity生命周期发生变化时, RequestManagerFragment的生命周期被调用, 其内部再通过RequestManager控制当前图片加载状态;
    二、Glide.load :
    2.1 RequestManager.load :
    RequestManager.load
    • 1、初始化RequestBuilder对象, RequestBuilder.ResourceType执行Drawable字节码对象;
    2.2 RequestBuilder.load :
    RequestBuilder.load
    • 1、仅仅是对RequestBuilder.model进行赋值操作;

    三、Glide.into :

    3.1 RequestBuilder.into :
    RequestBuilder.into
    • 1、由下文3.2可知, //5L获取的Target实际指向DrawableImageViewTarget;
    • 2、transcodeClass执行Drawable.class;
    3.2 GlideContext.buildImageViewTarget :
    GlideContext.buildImageViewTarget
    • 1、由上文2.1可知, clazz指向Drawable.class, 所以此时返回DrawableImageViewTarget对象的引用, 此时Z执行Drawable.class;
    3.2 RequestBuilder.into :
    RequestBuilder.into
    • 1、//8L与//18L将Request与DrawableImageViewTarget进行相互绑定;
    • 2、//19L完成RequestManager持有Request与DrawableImageViewTarget引用的操作;
    • 3、由下文3.3 ~ 3.4可知Request实际指向SingleRequest, SingleRequest持有RequestBuilder.model;
    • 4、//19L开始进入图片的加载;
    3.3 RequestBuilder.buildRequest :
    RequestBuilder.buildRequest
    • 1、省去了大量无关紧要的代码, 由下文3.4可知Request实际指向SingleRequest, 并且SingleRequest持有target, model的引用;
    3.4 SingleRequest.obtain :
    SingleRequest.obtain
    3.5 RequestManager.track :
    RequestManager.track
    • 1、上文1.5_//17L中初始化时RequestManager会创建一个RequestTracker的实例;
    • 2、//11L处开始指向数据加载操作;
    3.6 RequestTracker.newInstance :
    image.png
    3.7 RequestTracker.runRequest :
    RequestTracker.runRequest
    • 1、isPause默认为false, 跳转至//6L处, request实际指向SingleRequest;
    3.7 SingleRequest.begin :
    SingleRequest.begin
    • 1、//10L model = null时, 会加载占位图;
    • 2、只考虑尺寸正常情况下的数据加载, 尺寸不正常时, 在//21L会调用getSize经过一系列复杂计算, 又回到onSizeReady中;
    3.7 SingleRequest.onSizeReady :
    SingleRequest.onSizeReady
    • 1、注意//30L在调用engine.load时传入自身的引用, 对下文3.8的分析可知, load方法最后一个参数实际为ResourceCallback, 肯定是在某处回调了ResourceCallback的方法;
    3.8 Engine.load :
    Engine.load
    • 1、Glide也是用到了三级缓存, 先判断内存中是否有缓存, 如果没有, 则判断本地磁盘是否有缓存, 如果没有再从网络加载数据, //16L ~ // 30L即为有缓存时的操作;
    • 2、先跳至//31L分析从网络加载的逻辑, //44L将cb即SingleRequest的引用传给EngineJob, 然后在//45L开始异步加载数据;
    • 3、在//36L创建DecodeJob时, decodeJobFactory.build传入的最后以后参数为EngineJob, 而该方法最后一个参数为DecodeJob.Callback, 所以DecodeJob持有EngineJob, 将来在某一时刻回调EngineJob中的DecodeJob.Callback方法;
    3.9 EngineJob.start :
    EngineJob.start
    • 1、通过线程池触发DecodeJob.run的执行;
    3.10 DecodeJob.run :
    DecodeJob.run
    3.11 DecodeJob.runWrapped :
    DecodeJob.runWrapped
    • 1、下文3.12中可知, diskCacheStrategy实际指向DiskCacheStrategy.AUTOMATIC, 返回true, 此时currentGenerator指向ResourceCacheGenerator;
    • 2、由下文3.12 ~ 3.13可知, 最终currentGenerator会指向SourceGenerator实例;
    3.12 DecodeJob.diskCacheStrategy :
    DecodeJob.diskCacheStrategy
    3.13 DecodeJob.runGenerators :
    DecodeJob.runGenerators
    • 1、在3.11中, currentGenerator第一次指向ResourceCacheGenerator, 然后继续向下执行最终又会调用到runWrapper以及getNextStage方法让currentGenerator指向SourceGenerator实例;
    • 2、然后执行CurrentGenerator.startNext方法, 每次跟到这里都无功而返;
    3.14 SourceGenerator.startNext :
    SourceGenerator.startNext
    • 1、结合3.11中的//39L创建SourceGenerator实例时传入的参数可知, SourceGenerator内部的FetcherReadyCallback实际指向DecodeJob, 数据加载状态以回调的方式进行触发;
    • 2、然后helper.getLoadData开始真正的懵逼;
    • 3、由3.15 ~ 3.19可知在进行Glide初始化时, 会进行一系列的注册, 将加载图片所需要的modelClass与dataClass绑定在Entry中;
    • 4、由下文3.15 ~ 3.25可知, loadData为一系列加载图片方式的集合, 针对本文, loadData实际指向HttpGlideUrlLoader, 图片加载从HttpGlideUrlLoader.Fetcher开始;
    • 5、//25L在加载图片时, 将自身引用SourceGenerator传给Fetcher, 由下文3.26可知, 当从服务器获取流数据以后, 会通过DataCallback.onDataReady进行回调;
    3.15 GlideContext.getRegistry :
    GlideContext.getRegistry
    • 1、registry即为在初始化Glide时创建的Registry实例;
    3.16 Glide.glide :
    Glide.glide
    • 1、首先跳至//6L处register.append操作;
    3.17 Register.append :
    Register.append
    3.18 ModelLoaderRegistry.append :
    ModelLoaderRegistry.append
    3.19 MultiModelLoaderFactory.append :
    MultiModelLoaderFactory.append
    • 1、创建Entry对象, 缓存在entries中, Entry将modelClass, dataClass与对应的Factory绑定在一起;
    3.20 DecodeHelper.getLoadData :
    DecodeHelper.getLoadData
    3.21 Register.getModelLoaders :
    Register.getModelLoaders
    • 1、//7L ~ //43L以 modelClass为条件, 获取对应的List<ModelLoader>, 结合//38L可知, ModelLoader持有Entry对象的引用, Entry持有modelClass与dataClass;
    • 2、由下文3.23可知, loaders内部持有的ModelLoader由初始化Glide时传入的Model, Data字节码对象有关, 现在只针对HttpUriLoader进行分析;
    3.22 MultiModelLoaderFactory.build :
    MultiModelLoaderFactory.build
    • 1、由3.16 ~ 3.19可知, 如果以uri的形式从网络加载图片, 此时, Factory实际指向HttpUriLoader.Factory;
    3.23 HttpUriLoader.Factory.build :
    HttpUriLoader.Factory.build
    • 1、创建一个HttpUriLoader实例, 在构建HttpUriLoader实例的同时传入GlideUrl.class和InputStream.class;
    3.24 MultiModelLoaderFactory.build :
    MultiModelLoaderFactory.build
    • 1、3.23在构建HttpUriLoader时, 又会调用到MultiModelLoaderFactory.build并传入GlideUrl.class, InputStream.class, 结合3.16可知//13L调用build时, 跳至3.22中的factory实际指向HttpGlideUrlLoader.Factory;
    3.25 HttpGlideUrlLoader.Factory.build :
    HttpGlideUrlLoader.Factory.build
    • 直接返回LoadData对象, 该实例持有HttpUrlFetcher实例的引用;
    3.26 HttpUrlFetcher.loadData :
    HttpUrlFetcher.loadData
    • 1、Glide内部使用HttpURLConnection方式从服务器获取流数据, 然后通过callback进行回调;
    • 2、由上文3.14可知, this实际指向SourceGenerator;
    四、数据处理 :
    • 第三部分into从服务器获取流数据以后, 需要对流数据进行编码和显示, 对流数据的处理是一个大模块, 放在第四部分;
    4.1 SourceGenerator.onDataReady :
    SourceGenerator.onDataReady
    • 1、在HttpUrlFetcher中获取的流数据被回调到SourceGenerator.onDataReady, 而SourceGenerator内部的FetcherReadyCallback cb由上文3.11可知, 实际指向DecodeJob;
    4.2 DecodeJob.onDataFetcherReady :
    DecodeJob.onDataFetcherReady
    • 1、//17L对流数据进行处理, 跳至//25L将流数据封装至Resource对象中;
    • 2、//27L对流数据进行编码和释放;
    4.3 DecodeJob.decodeFromData :
    DecodeJob.decodeFromData
    • 1、图片流数据解析又依赖于DecodeHelper, 在3.20中可知, 从网络获取图片流数据也是要依赖于DecodeHelper;
    • 2、下文4.4 ~ 4.7可知, path内部持有DecodePath对象, DecodePath内部又持有一个由StreamBitmapDecoder和StreamGifDecoder组成的集合;
    4.4 DecodeHelper.getLoadPath :
    DecodeHelper.getLoadPath
    • 1、代码似曾相识, 又依赖于Register;
    4.5 Register.getLoadPath :
    Register.getLoadPath
    • 1、与加载流数据的套路很相似, 重点在//21L处, 从服务器获取的Data.class实际指向InputStream.class, 所以切换到Glide初始化时Register填充数据处;
    • 2、对下文4.6的分析可知registeredResourceClasses实际持有Birmap.class, BitmapDrawable.class, GifDrawable.class三个字节码对象;
    • 3、由上文2.1可知Transcode实际指向Drawable, 在对下文4.7的分析可知//24L过滤掉了Bitmap.class;
    • 4、然后在结合4.6中的append操作匹配InputStream.class以及BitmapDrawable.class, GifDrawable.class得出BitmapDrawableDecoder和StreamGifDecoder, 这两个即为后续要用到的图片流数据解码器;
    • 5、decodePaths持有两个DecodePath, 一个DecodePath持有BitmapDrawableDecoder, 另外一个DecodePath持有StreamGifDecoder;
    4.6 Glide.Glide :
    Glide.Glide
    • 1、通过InputStream.class匹配了Birmap.class, BitmapDrawable.class, GifDrawable.class, 所以在4.5中//21L实际为这三者的集合;
    4.7 TranscoderRegistry.getTranscodeClasses :
    TranscoderRegistry.getTranscodeClasses
    • 1、//9L进行匹配操作, 过滤掉了Bitmap.class;
    4.8 DecodeJob.runLoadPath :
    五、装载进Bitmap :
    • 数据解码懒得去操心了, 直接先看如何使用Bitmap;
    5.1 Downsampler.decode :
    Downsampler.decode
    • 1、//14L将流装载进Bitmap中, 然后将InputStream转换成的字节数组bytesForOptions缓存起来, 所以内存缓存缓存的是字节数组对象, 而不是Bitmap;
    • 2、下文5.2可知//17L返回BitmapResource实例, 该实例持有bitmap的引用;
    • 3、然后几经周转又回到了4.2//27L的notifyEncodeAndRelease方法;
    5.2 BitmapResource.obtain :
    BitmapResource.obtain
    • 返回BitmapResource对象, 该对象持有Bitmap的引用;
    5.3 DecodeJob.notifyEncodeAndRelease :
    DecodeJob.notifyEncodeAndRelease
    • 流数据经过解码, 装载, 包装以后, 在//31L处被回调, 由上文3.7可知, callback实际指向EngineJob;
    5.4 EngineJob.onResourceReady :
    EngineJob.onResourceReady
    • 1、通过Handler.sendToTarget, 将后续图片显示等操作切换到主线程;
    5.5 EngineJob.handleResultOnMainThread :
    EngineJob.handleResultOnMainThread
    • 1、由上文3.7可知, cb实际指向SingleRequest;
    5.6 SingleRequest.onResourceReady :
    SingleRequest.onResourceReady
    • 3.2 ~ 3.7可知target实际指向DrawableImageViewTarget;
    5.7 DrawableImageViewTarget.onResourceReady :
    DrawableImageViewTarget.onResourceReady
    • 图片最终被加载到ImageView中;
    六、关于缓存(内存缓存) :
    6.1 EngineJob.handleResultOnMainThread :
    EngineJob.handleResultOnMainThread
    • 1、//32L 构建EngineKey实例;
    • 2、//36L构建EngineJobFactory实例时传入Engine指向EngineJobListener, 所以//25L触发Engine.onEngineJobComplete指向;
    • 3、//25L图片资源在以弱引用被缓存进activeResources之前会触发engineResource.acquire以及缓存、显示完成之后触发engineResource.release, 将图片资源缓存进LruResourceCache中, 并且从activeResources中移除;
    6.2 Engine.onEngineJobComplete :
    Engine.onEngineJobComplete
    • //6L图片资源以弱引用的方式被缓存在activeResources中;
    6.3 EngineResource.acquire/release :
    EngineResource.acquire/release
    • 1、当acquire == 0时, 将cacheKey从activeResources中移除, 即移除弱引用缓存;
    • 2、结合上文1.2-> memoryCache实际指向LruResourceCache, LruResourceCache内部维护的是LinkedHashMap, 实现LRU缓存图片资源;
    七、关于缓存(磁盘缓存) :

    相关文章

      网友评论

          本文标题:开源框架_01Glide

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