平方X 发表于 2018-4-4 18:45:33

[2526]Glide 学习笔记


http://blog.csdn.net/guolin_blog/article/details/53759439

* 默认使用 RGB_565 是在哪里初始化设置加载的
* 缓存策略,是如何缓存与读取缓存的

郭霖 大佬的文章已经分析了很多,于是按他的文章进行学习,也学习一下详细分析的一些步骤。

# 0x01 Glide的基本用法

## 配置
    apply plugin: 'kotlin-kapt'
    ...
    compile 'com.github.bumptech.glide:glide:4.5.0'
    kapt 'com.github.bumptech.glide:compiler:4.5.0'
    ...
    <uses-permission android:name="android.permission.INTERNET" />

## 使用
v3 与 v4 的用法区别还是很大的,也是醉醉的。

Glide 改为了 GlideApp

      GlideApp.with(this)
                .load("https://www.baidu.com/img/bd_logo1.png")
                .placeholder(R.mipmap.ic_launcher)
                .error(R.mipmap.ic_launcher_round)
                .transition(DrawableTransitionOptions.withCrossFade(3000))
                .circleCrop()
                .override(50, 100)
                .diskCacheStrategy(DiskCacheStrategy.NONE)
                .into(iv)
               
               
# 0x02 执行流程
> 应该认准一个功能点,然后去分析这个功能点是如何实现的。但只要去追寻主体的实现逻辑即可,千万不要试图去搞懂每一行代码都是什么意思,那样很容易会陷入到思维黑洞当中,而且越陷越深。因为这些庞大的系统都不是由一个人写出来的,每一行代码都想搞明白,就会感觉自己是在盲人摸象,永远也研究不透。如果只是去分析主体的实现逻辑,那么就有比较明确的目的性,这样阅读源码会更加轻松,也更加有成效。
## with
通过 context 参数创建一个 RequestManagerRetriever,然后调用 com.bumptech.glide.manager.RequestManagerRetriever 的 get 方法。

创建时,会添加一个 com.bumptech.glide.manager.RequestManagerFragment ,用于监听生命周期。

## load
已经简化为一个 RequestBuilder

## into
* 创建 ViewTarget 和 Request
* 调用 Request.begin
* 回调 Request.onSiezeReady
* Engine 创建 EnginJob ,执行 EngineJob#start
* DecodeJob 生成 DataFetcherGenerator,创建 DataFetcher 执行 loadData
* 回调 onDataFetcherReady
* DecodeJob 执行 Decode
* EnginJob 回调 onResourceReady,通过 Handler 传到主线程,回调 Request
* Request 回调 onResourceReady
* ViewTarget 回调 onResourceReady

## 相关问题
### ViewTarget 是如何创建的
调用的 GlideContext#buildImageViewTarget ,使用 imageViewTargetFactory 创建
该 Factory 在 Glide 初始时,在初始化时 GlideContent 时 new 了一个。

### Request 是如何创建的
RequestBuilder#buildRequest 方法,在 buildRequestRecursive 中绕啊绕,但因为执行 obtainRequest 所以生成 SingleRequest

### DataFetcherGenerator 是如何工作的
在 getNextGenerator 中生成,传递的 decodeHelper 是 DecodeJob 初始化的。
DecodeHelper#getLoadData 通过 Registry#getModelLoaders 来获取 ModelLoader
这些 ModelLoader 在 Glide 初始化时注册,调用 ModelLoader#buildLoadData 生成 LoadData
然后调用 loadData.fetcher.loadData
com.bumptech.glide.load.model.MultiModelLoader.MultiFetcher#loadData
com.bumptech.glide.load.data.HttpUrlFetcher#loadData

### 加载的数据是如何 decode 的
在 HttpUrlFetcher#loadData 中返回 InputStream
传到 SourceGenerator#onDataReady
再到 DecodeJob#onDataFetcherReady,在 DecodeJob 处理,获取 LoadPath
执行 LoadPath#load
DecodePath#decode
ResourceDecoder#decode
Downsampler#decode
Downsampler#calculateScaling
Downsampler#calculateConfig

### 默认的 Config 是怎么换成 ARGB_8888
    在 com.bumptech.glide.load.resource.bitmap.Downsampler#decode(java.io.InputStream, int, int, com.bumptech.glide.load.Options, com.bumptech.glide.load.resource.bitmap.Downsampler.DecodeCallbacks)
    中有 DecodeFormat decodeFormat = options.get(DECODE_FORMAT);
    public static final Option<DecodeFormat> DECODE_FORMAT = Option.memory(
      "com.bumptech.glide.load.resource.bitmap.Downsampler.DecodeFormat", DecodeFormat.DEFAULT);
   
    com.bumptech.glide.load.DecodeFormat#DEFAULT
    public static final DecodeFormat DEFAULT = PREFER_ARGB_8888_DISALLOW_HARDWARE;
而 3.0 的默认值为 PREFER_RGB_565

### 有透明度时是如何处理的
    在 com.bumptech.glide.load.resource.bitmap.Downsampler#calculateConfig 有判断
    获取类型 DefaultImageHeaderParser#getType(com.bumptech.glide.load.resource.bitmap.DefaultImageHeaderParser.Reader)
    通过读取前面部分字节判断类型,然后判断是否有为透明度 PNG_A 和 WEBP_A 有

### placeholder 是如何生效的
持有 com.bumptech.glide.RequestBuilder#requestOptions
在创建 Request 时传递过去,在 com.bumptech.glide.request.SingleRequest#begin 方法中调用了
com.bumptech.glide.request.target.Target#onLoadStarted,此时传的 placeholder 即从 requestOptions 中获取。

### error 是如何生效的
    com.bumptech.glide.load.data.HttpUrlFetcher#loadData 回调
    com.bumptech.glide.load.engine.SourceGenerator#onLoadFailed再回调
    com.bumptech.glide.load.engine.DecodeJob#onDataFetcherFailed
    com.bumptech.glide.load.engine.DecodeJob#notifyFailed
    com.bumptech.glide.request.SingleRequest#onLoadFailed(com.bumptech.glide.load.engine.GlideException, int)
    com.bumptech.glide.request.SingleRequest#setErrorPlaceholder

### override 如何生效
override 宽高从 RequestBuilder → Request → Engine → DecodeJob ,最后传给 decode 去了,所以只用于加载出的数据的 decode

### transform 怎么生效
decode 成功后,回调 com.bumptech.glide.load.engine.DecodeJob#onResourceDecoded
之前通过 com.bumptech.glide.request.RequestOptions#transform(com.bumptech.glide.load.Transformation<android.graphics.Bitmap>)
添加到 transformations 中,回调时执行
com.bumptech.glide.load.Transformation#transform


# 0x03 缓存
## 内存缓存
    Glide 的构造,在 com.bumptech.glide.GlideBuilder#build 中
    new 了一个 LruResourceCache,
    作为参数 new 了一个 Engine
    engine 作为参数 new 了 glide

### 弱引用
    com.bumptech.glide.load.engine.Engine#load
    com.bumptech.glide.load.engine.Engine#loadFromActiveResources
    弱引用保存加载中的缓存
   
    保存
    com.bumptech.glide.load.engine.EngineJob#handleResultOnMainThread
    com.bumptech.glide.load.engine.Engine#onEngineJobComplete
    以及下面的从外部加载
### LruCache
com.bumptech.glide.load.engine.Engine#loadFromCache
TODO Lru 原理

    com.bumptech.glide.load.engine.EngineResource#acquire
    com.bumptech.glide.load.engine.EngineResource#release
    com.bumptech.glide.load.engine.Engine#onResourceReleased
   
内存缓存,先从 activeResources 读取。
如果没有,则从 LruCache 读取,读取后移除,加入 activeResources
释放使用时,从 activeResources 移除,写入 LruCache

## 硬盘缓存
    getNextGenerator 返回 ResourceCacheGenerator 或 DataCacheGenerator
    然后分别在它们的 startNext 中获取,注意 key 的不同
   
    写入:
    com.bumptech.glide.load.engine.DecodeJob#onDataFetcherReady
    com.bumptech.glide.load.engine.DecodeJob#decodeFromRetrievedData
    先调用 com.bumptech.glide.load.engine.DecodeJob#decodeFromData
    回调 com.bumptech.glide.load.engine.DecodeJob#onResourceDecoded
    com.bumptech.glide.load.engine.DecodeJob.DeferredEncodeManager#init
   
    然后调用 com.bumptech.glide.load.engine.DecodeJob#notifyEncodeAndRelease
    com.bumptech.glide.load.engine.DecodeJob.DeferredEncodeManager#encode
   
# 0x04 自定义组件
前面还有两篇,回调与监听,图片变换,这里不详述了。
## 如何加载的
    通过注解,生成了 GeneratedAppGlideModuleImpl,内部包含自定义的 AppGlideModule
    相关操作传到 GeneratedAppGlideModuleImpl,再转到自定义的 AppGlideModule
   
    com.bumptech.glide.Glide#getAnnotationGeneratedGlideModules
   
    也可以获取 manifest 中的 com.bumptech.glide.module.ManifestParser#parse

# LruCache
(https://github.com/bumptech/glide)
(https://github.com/JakeWharton/DiskLruCache)
[ Android DiskLruCache完全解析,硬盘缓存的最佳方案](http://blog.csdn.net/guolin_blog/article/details/28863651)

页: [1]
查看完整版本: [2526]Glide 学习笔记