Android干货Android TipsAndroid App

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

2017-10-20  本文已影响74人  肖丹晨

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

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

版权归作者所有,如有转发,请注明文章出处:http://www.jianshu.com/u/d43d948bef39

相关文章:

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

1. Request管理机制

在上一篇中我们剖析了Glide的生命周期绑定机制,这一篇我们紧接着Glide的处理流程来学习一下Glide的请求管理机制。
我们先来看一下Glide的最简单的使用代码示例:

ImageView ivImage = (ImageView) findViewById(R.id.ivImage);
Glide.with(ivImage.getContext()) //获取RequestManager对象
     .load(url); //设置Request对象需要的资源链接
     .into(ivImage); //获取Request对象并绑定viewTarget -> 发起网络请求

该段代码十分简洁,但是内部实现的功能却十分的强大,比如:

针对这些问题,后面将会一一展开剖析。

2. request及其生命周期管理

3. Glide请求管理机制类图

RequestManager是如何生成request并管理request队列的?
老规矩,先上图:


Glide请求管理机制类图

如图:

  1. RequestManager持有一个RequestTracker对象requestTracker。
  2. requestTracker对象维护request的队列集合
  3. RequestManager的load()函数用于获取GenericRequestBuilder对象(其实是子类对象)
  1. GenericRequestBuilder的into()方法是实际产生request和消费request的地方。

3.1 GenericRequestBuilder的into(target)方法

public <Y extends Target<TranscodeType>> Y into(Y target) {
    Util.assertMainThread();
    if (target == null) {
      throw new IllegalArgumentException("You must pass in a non null Target");
    }
    if (!isModelSet) {
      throw new IllegalArgumentException("You must first set a model (try #load())");
    }
  
    //因为target和request是相互绑定的,所以考虑到复用的情景时,可以先获取一下request
    Request previous = target.getRequest();
   
    //previous != null说明target有复用,需要释放之前绑定的资源
    //注意:request内部是绑定了资源的,这里还没有讲到,先知道这回事,后面会讲
    if (previous != null) {
        //释放资源,防内存泄漏
        //这段代码是精华,需要好好体会:
        //Glidek肯定支持view的复用(对吧?),那么复用的view资源是如何绑定和释放的?
        //这里就是资源释放的地方(入口),资源在何时绑定会在后续的课程讲到。
        previous.clear();
        requestTracker.removeRequest(previous);
        previous.recycle();
    }
   
    //获取需求对象(对象绑定了target)
    Request request = buildRequest(target);
    //target绑定需求
    target.setRequest(request);
    //因为target具有生命周期,即实现了LifecycleListener方法,所以将其注册给ActivityFragmentLifecycle统一管理(不知道是啥的去看上一篇文章)
    lifecycle.addListener(target);
    //将需求加入队列并执行需求
    //注意是单线程
    requestTracker.runRequest(request);
  
    return target;
}

3.2 request的生命周期管理

3.2.1 RequestManager

下面让我们看看RequestManager在各个生命周期回调里都做了什么

@Override
public void onStart() {
    resumeRequests();
}
 
@Override
public void onStop() {
    pauseRequests();
}
 
@Override
public void onDestroy() {
    requestTracker.clearRequests();
}
 
public void pauseRequests() {
    Util.assertMainThread();
    requestTracker.pauseRequests();
}
 
public void resumeRequests() {
    Util.assertMainThread();
    requestTracker.resumeRequests();
}
//下面的两个回调其实和request的关系没有那么直接,先放在这里留个印象    
public void onTrimMemory(int level) {
    glide.trimMemory(level);
}
 
public void onLowMemory() {
    glide.clearMemory();
}

代码很清楚了吧。细心的同学可能注意到了onTrimMemory(int level)和onLowMemory(),这俩货是系统在资源不足时调用的,说白了就是释放内存,具体怎么搞得,后续文章会专门讲到Glide的内存管理机制(也是精华)

3.2.2 requestTracker

最后让我们看看requestTracker都干啥了吧

public class RequestTracker {
    private final Set<Request> requests = Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
  
    @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
    private final List<Request> pendingRequests = new ArrayList<Request>();
  
    private boolean isPaused;
  
    /**
    * Starts tracking the given request.
    */
    public void runRequest(Request request) {
        requests.add(request);
        if (!isPaused) {
            request.begin();
        } else {
            pendingRequests.add(request);
        }
    }
  
    // Visible for testing.
    void addRequest(Request request) {
        requests.add(request);
    }
  
    /**
    * Stops tracking the given request.
    */
    public void removeRequest(Request request) {
        requests.remove(request);
        pendingRequests.remove(request);
    }
   
    /**
    * Returns {@code true} if requests are currently paused, and {@code false} otherwise.
    */
    public boolean isPaused() {
        return isPaused;
    }
   
    /**
    * Stops any in progress requests.
    */
    public void pauseRequests() {
        isPaused = true;
        for (Request request : Util.getSnapshot(requests)) {
            if (request.isRunning()) {
                request.pause();
                pendingRequests.add(request);
            }
        }
    }
  
    /**
    * Starts any not yet completed or failed requests.
    */
    public void resumeRequests() {
        isPaused = false;
        for (Request request : Util.getSnapshot(requests)) {
            if (!request.isComplete() && !request.isCancelled() && !request.isRunning()) {
            request.begin();
            }
        }
        pendingRequests.clear();
    }
  
    /**
    * Cancels all requests and clears their resources.
    */
    public void clearRequests() {
        for (Request request : Util.getSnapshot(requests)) {
            request.clear();
        }
        pendingRequests.clear();
    }
  
    /**
    * Restarts failed requests and cancels and restarts in progress requests.
    */
    public void restartRequests() {
      for (Request request : Util.getSnapshot(requests)) {
          if (!request.isComplete() && !request.isCancelled()) {
              // Ensure the request will be restarted in onResume.
              request.pause();
              if (!isPaused) {
                  request.begin();
              } else {
                  pendingRequests.add(request);
              }
           }
        }
    }
}

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

上一篇下一篇

猜你喜欢

热点阅读