参考文章 :
- Android图片加载框架最全解析(一), Glide的基本用法
- Android图片加载框架最全解析(二), 从源码的角度理解Glide的执行流程
- Android图片加载框架最全解析(三),深入探究Glide的缓存机制
- Android 图片加载框架Glide4.0源码完全解析(一)
- Android 图片加载框架Glide4.0源码完全解析(二)
- Glide源码分析之缓存处理
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.obtain3.5 RequestManager.track :
RequestManager.track- 1、上文1.5_//17L中初始化时RequestManager会创建一个RequestTracker的实例;
- 2、//11L处开始指向数据加载操作;
3.6 RequestTracker.newInstance :
image.png3.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.run3.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.diskCacheStrategy3.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.append3.18 ModelLoaderRegistry.append :
ModelLoaderRegistry.append3.19 MultiModelLoaderFactory.append :
MultiModelLoaderFactory.append- 1、创建Entry对象, 缓存在entries中, Entry将modelClass, dataClass与对应的Factory绑定在一起;
3.20 DecodeHelper.getLoadData :
DecodeHelper.getLoadData3.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缓存图片资源;
网友评论