盒子
盒子
文章目录
  1. 资源请求和回调机制类图
  2. request开启请求
  3. 获取Engin对象并封装任务
  4. 执行任务获取数据并解析

跟着源码学设计:Glide框架及源码解析(四)

前言

近期研究了一下Glide的图片加载框架,在这里和大家分享一下。由于代码研读有限,难免有错误的地方,了解的童鞋还望指正。学习小组QQ群: 193765960。

本篇是Glide框架及源码解析的第四篇,更多文章敬请关注后续文章。如果这篇文章对大家学习Glide有帮助,还望大家多多转载。

版权归作者所有,如有转发,请注明文章出处:https://xiaodanchen.github.io/archives/

相关文章:

跟着源码学设计:Glide框架及源码解析(一)
跟着源码学设计:Glide框架及源码解析(二)
跟着源码学设计:Glide框架及源码解析(三)
跟着源码学设计:Glide框架及源码解析(四)
跟着源码学设计:Glide框架及源码解析(五)

在之前的文章中,我们已经知道了Glide请求是如何被加载到请求队列中并执行的,也了解了资源是如何管理的。本篇文章我们将探究一下资源是如何获取并分发的。

资源请求和回调机制类图

资源请求和回调机制类图

request开启请求

request被加载到requestTracker中统一管理启动获取资源,代码如下:

1
2
3
4
5
6
7
8
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}

  • request的执行从其begin()方法开始:
    1
    2
    3
    4
    5
    6
    7
    8
    public void runRequest(Request request) {
    requests.add(request);
    if (!isPaused) {
    request.begin();
    } else {
    pendingRequests.add(request);
    }
    }

获取Engin对象并封装任务

  • 获取engine对象,在load()方法中创建EnginJob任务
  • 为Enginjob创建异步线程EnginRunnable
  • 为EnginRunnable初始化资源获取解析任务DecodJob
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
    DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
    Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
    Util.assertMainThread();
    long startTime = LogTime.getLogTime();
    final String id = fetcher.getId();
    //获取key
    EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
    loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
    transcoder, loadProvider.getSourceEncoder());
    //查找LruResourceCache
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
    cb.onResourceReady(cached);
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    logWithTimeAndKey("Loaded resource from cache", startTime, key);
    }
    return null;
    }
    //查找ActiveResourceCache
    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    if (active != null) {
    cb.onResourceReady(active);
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    logWithTimeAndKey("Loaded resource from active resources", startTime, key);
    }
    return null;
    }
    //任务排重
    EngineJob current = jobs.get(key);
    if (current != null) {
    current.addCallback(cb);
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    logWithTimeAndKey("Added to existing load", startTime, key);
    }
    return new LoadStatus(cb, current);
    }
    //创建EngineJob
    EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
    //创建DecodeJob:注意fetcher(数据加载器)
    DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
    transcoder, diskCacheProvider, diskCacheStrategy, priority);
    //创建任务线程
    EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
    //将任务加入管理队列
    jobs.put(key, engineJob);
    engineJob.addCallback(cb);
    //启动任务
    engineJob.start(runnable);
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    logWithTimeAndKey("Started new load", startTime, key);
    }
    return new LoadStatus(cb, engineJob);
    }

执行任务获取数据并解析

  • DecodJob通过数据获取器DataFetcher获取数据文件(流)
    request被加载到requestTracker中统一管理启动获取资源,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    //EngineRunnable的run()方法
    public void run() {
    if (isCancelled) {
    return;
    }
    Exception exception = null;
    Resource<?> resource = null;
    try {
    resource = decode();
    } catch (Exception e) {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    Log.v(TAG, "Exception decoding", e);
    }
    exception = e;
    }
    if (isCancelled) {
    if (resource != null) {
    resource.recycle();
    }
    return;
    }
    if (resource == null) {
    onLoadFailed(exception);
    } else {
    onLoadComplete(resource);
    }
    }
    private Resource<?> decode() throws Exception {
    if (isDecodingFromCache()) {
    return decodeFromCache();
    } else {
    return decodeFromSource();
    }
    }
    private Resource<?> decodeFromSource() throws Exception {
    return decodeJob.decodeFromSource();
    }
  • 数据解析器对data数据解析生成resource资源对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    private Resource<T> decodeSource() throws Exception {
    Resource<T> decoded = null;
    try {
    long startTime = LogTime.getLogTime();
    //数据加载器获取数据
    final A data = fetcher.loadData(priority);
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    logWithTimeAndKey("Fetched data", startTime);
    }
    if (isCancelled) {
    return null;
    }
    //data数据解析生成resource资源对象
    decoded = decodeFromSourceData(data);
    } finally {
    fetcher.cleanup();
    }
    return decoded;
    }
    //HttpUrlFetcher:网络资源加载器
    public InputStream loadData(Priority priority) throws Exception {
    return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
    }
  • resource资源进一步封装成为EnginResource对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //Runnable的方法,在run()方法中调用
    private void onLoadComplete(Resource resource) {
    manager.onResourceReady(resource);
    }
    //manager.onResourceReady(resource)实际回调了Enginjob的接口实现
    public void onResourceReady(final Resource<?> resource) {
    this.resource = resource;
    MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
    }
  • 通过监听接口回传EnginResource对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    private void handleResultOnMainThread() {
    if (isCancelled) {
    resource.recycle();
    return;
    } else if (cbs.isEmpty()) {
    throw new IllegalStateException("Received a resource without any callbacks to notify");
    }
    engineResource = engineResourceFactory.build(resource, isCacheable);
    hasResource = true;
    // Hold on to resource for duration of request so we don't recycle it in the middle of notifying if it
    // synchronously released by one of the callbacks.
    engineResource.acquire();
    listener.onEngineJobComplete(key, engineResource);
    for (ResourceCallback cb : cbs) {
    if (!isInIgnoredCallbacks(cb)) {
    engineResource.acquire();
    //回传engineResource到request中,request获取到资源后开始刷新UI
    cb.onResourceReady(engineResource);
    }
    }
    // Our request is complete, so we can release the resource.
    engineResource.release();
    }

(本篇是Glide框架及源码解析的第四篇,更多文章敬请关注后续文章。版权归作者所有,如有转发,请注明文章出处:原文链接

扫描加群
好好学习,天天向上!