Glide源码解析

glide

为什么选择 glide 框架?

Picasso 框架

已无人维护。直接 pass 掉。

fresco 框架

用法较复杂,不如 glide 的用法简洁。优势是能大大减少 OOM 的概率,因为图片不在放在 Java Heap 中,而是放在 Ashmem(匿名共享内存)中。适用于高性能加载大量图片的场景。sdk 大小为 500 kb.

glide 框架

sdk大小 440 Kb,在可以接受的范围内。适合图片加载量不大的 app 使用。从网络加载速度和加载本地缓存的速度很快。android 官方也推荐使用。

程序整体架构如图:

架构图

Glide为单例类。

  1. Glide.with(this) 会创建 RequestManager ,RequestManager 是 Request 的管理类,根据activity或者fragment生命周期的变化对请求做不同的处理。具体流程如下:在参数 activity 上面创建一个隐藏的 RequestManagerFragment,该fragment用于同步activity生命周期的变化,具体方法是利用ActivityFragmentLifecycle类将生命周期的变化回调给RequestManager。

    一个 activity 对应一个 FragmentManager,FragmentManager 对应一个透明的 RequestManagerFragment,RequestManagerFragment 对应一个 RequestManager。所以一个 activity 对应一个 RequestManager 实例 。

  2. Glide.with(this).load(url)会创建RequestBuilder。RequestBuilder用来配置请求、加载图片

  3. Glide.with(this).load(url).into(imageview):

    buildRequest 方法构建请求返回 request 对象;

    requestManager.track(target, request) 方法里会调用 requestTracker.runRequest(request) 方法,从而执行 request 的 begin() 方法,begin 方法里会判断请求的状态并做不同的处理。当view的大小确定以后,会执行onSizeReady方法,重点看onSizeReady里的engine.load()方法:

    ​ 从 ActiveResources 里获取缓存(ActiveResources 保存弱引用的集合),生命周期短、没有大小限制;

    ​ 从MemoryCache里获取缓存,使用 LRU 算法保证内存不超过限定值;

    ​ 使用 engineJob 启动 decodeJob,run方法里调用 dataFetcher 的 loadData方法加载数据(从网络、本地加载),获取完成后使用 Encoder 将数据存入磁盘缓存文件中(sourceGenerator),同时使用对应的解码器将原始数据转换为相应的资源文件.

    当资源加载完成时,会执行 SingleRequest类 的 onResourceReady 方法。依次跟下去会执行 target.onResourceReady 方法:

    1
    target.onResourceReady(result, animation)

    onResourceReady 方法有多种实现,以 ImageViewTarget 类的实现为例:

    1
    2
    3
    4
    5
    6
    7
    public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
    if (transition == null || !transition.transition(resource, this)) {
    setResourceInternal(resource);
    } else {
    maybeUpdateAnimatable(resource);
    }
    }

    进入 setResourceInternal 方法,发现其调用了一个抽象方法 setResource:

    1
    protected abstract void setResource(@Nullable Z resource);

    setResource 方法也有多个实现。看一下 BitmapImageViewTarget 类的实现:

    1
    2
    3
    protected void setResource(Bitmap resource) {
    view.setImageBitmap(resource);
    }

    可以看到,上面这行代码调用 android 系统 API 把图片资源设置给 view 以完成显示工作。