美文网首页
Android-Glide源码解析

Android-Glide源码解析

作者: zzq_nene | 来源:发表于2020-08-23 22:01 被阅读0次

一、LruCache

要分析Glide的源码,首先就需要分析LruCache。LruCache是基于LinkedHashMap实现的,LinkedHashMap是一个双向链表,LinkedHashMap的实现其实与HashMap类似,具体的LinkedHashMap的分析,可以看
LinkedHashMap源码解析
而LruCache中初始化LinkedHashMap对象的时候,参数中accessOrder传入的是true,这是代表LinkedHashMap支持访问排序,即按访问顺序进行排序,将最后访问的放在链表最后面。

this.map = new LinkedHashMap<K, V>(0, 0.75f, true);

1.LruCache的类中的属性

    // 用于存储LruCache中的缓存键值对
    private final LinkedHashMap<K, V> map;

    // 定义缓存的大小
    private int size;
    // 缓存容量的最大容积
    private int maxSize;

    // put加入的缓存元素个数
    private int putCount;
    // 从缓存中取出的元素个数为null的时候,在get中createValue时计数
    private int createCount;
    // 移除元素的数量(trimToSize方法中移除最老的元素时调用)
    private int evictionCount;
    // 从缓存中取出元素不为null的计数
    private int hitCount;
    // 从缓存中取出元素结果为null的计数
    private int missCount;

2.LruCache的put方法

    public final V put(K key, V value) {
        if (key == null || value == null) {
            throw new NullPointerException("key == null || value == null");
        }

        V previous;
        synchronized (this) {
            putCount++;
            // 计算当前条目数,默认是加1
            size += safeSizeOf(key, value);
            // 判断当前map是否已经存在key所对应的value
            previous = map.put(key, value);
            // 如果存在,则previous不为null,则size需要重新减去1,因为只是替换了map中的元素,而没有真正的增加
            if (previous != null) {
                size -= safeSizeOf(key, previous);
            }
        }

        // 如果map中key对应的元素已经存,则将被替换了的元素和key,通过entryRemoved方法回调出去
        // 在LruCache中entryRemoved是默认空实现,需要开发者自己实现
        // 比如:被替换的元素回调给开发者,由开发者将被替换(其实就是从LruCache中移除的缓存)元素加入到磁盘缓存中
        if (previous != null) {
            entryRemoved(false, key, previous, value);
        }
        // 移除最近最久未被使用的元素
        trimToSize(maxSize);
        return previous;
    }

3.LruCache的get方法

    public final V get(K key) {
        if (key == null) {
            throw new NullPointerException("key == null");
        }

        V mapValue;
        synchronized (this) {
            // 从LinkedHashMap中取出key对应的value
            mapValue = map.get(key);
            // 如果value不为null,则可以直接返回,且hitCount加1
            if (mapValue != null) {
                hitCount++;
                return mapValue;
            }
            // 如果value为null,则missCount++
            missCount++;
        }

        /*
         * 尝试创建一个值。 这可能需要很长时间,并且当create()返回时,映射可能会有所不同。
         * 如果在create()工作时向地图添加了冲突值,则我们将该值保留在地图中并释放创建的值。
         */
        // 这里默认是返回null
        // 可以由开发者自己实现create方法,通过key创建对应的value,然后在key为null的时候,在get方法中加入LinkedHashMap中
        V createdValue = create(key);
        if (createdValue == null) {
            return null;
        }

        synchronized (this) {
            createCount++;
            mapValue = map.put(key, createdValue);

            if (mapValue != null) {
                // There was a conflict so undo that last put
                map.put(key, mapValue);
            } else {
                size += safeSizeOf(key, createdValue);
            }
        }

        if (mapValue != null) {
            entryRemoved(false, key, createdValue, mapValue);
            return mapValue;
        } else {
            trimToSize(maxSize);
            return createdValue;
        }
    }

4.LruCache的remove方法

    public final V remove(K key) {
        if (key == null) {
            throw new NullPointerException("key == null");
        }

        V previous;
        synchronized (this) {
            // 通过LinkedHashMap的remove方法移除对应的元素
            previous = map.remove(key);
            // 元素数目减少1
            if (previous != null) {
                size -= safeSizeOf(key, previous);
            }
        }
        // 如果map中key对应的元素已经存,则将被替换了的元素和key,通过entryRemoved方法回调出去
        // 在LruCache中entryRemoved是默认空实现,需要开发者自己实现
        // 比如:被替换的元素回调给开发者,由开发者将被替换(其实就是从LruCache中移除的缓存)元素加入到磁盘缓存中
        // 其实entryRemoved方法所做的工作,就是由开发者自定义进行移除后的工作
        if (previous != null) {
            entryRemoved(false, key, previous, null);
        }

        return previous;
    }

5.LruCache的trimToSize方法

移除最近最久未被使用的元素

    private void trimToSize(int maxSize) {
        while (true) {
            K key;
            V value;
            synchronized (this) {
                if (size < 0 || (map.isEmpty() && size != 0)) {
                    throw new IllegalStateException(getClass().getName()
                            + ".sizeOf() is reporting inconsistent results!");
                }

                if (size <= maxSize) {
                    break;
                }

                // BEGIN LAYOUTLIB CHANGE
                // get the last item in the linked list.
                // This is not efficient, the goal here is to minimize the changes
                // compared to the platform version.
                Map.Entry<K, V> toEvict = null;
                // 获取链表中的最后一个节点
                for (Map.Entry<K, V> entry : map.entrySet()) {
                    toEvict = entry;
                }
                // END LAYOUTLIB CHANGE

                if (toEvict == null) {
                    break;
                }
                // 取出最后一个节点的key和value
                key = toEvict.getKey();
                value = toEvict.getValue();
                // 从LinkedHashMap中移除最后一个元素
                map.remove(key);
                // 移除最后一个元素之后,元素个数size数目减少1
                size -= safeSizeOf(key, value);
                evictionCount++;
            }
            // 通知该key和value被移除
            entryRemoved(true, key, value, null);
        }
    }

二、Glide中防止OOM的做法

因为Glide是采用在一个空的Fragment来监听生命周期,而Fragment又会通过

android.content.ComponentCallbacks2#onTrimMemory(int)

方法回调,又因为Glide注册了这个监听回调,在Fragment的performTrimMemory方法中会针对回调做事件的分发,当Glide接收到事件之后,又会调用Glide的trimMemory方法

  public void trimMemory(int level) {
    // Engine asserts this anyway when removing resources, fail faster and consistently
    Util.assertMainThread();
    // Request managers need to be trimmed before the caches and pools, in order for the latter to
    // have the most benefit.
    for (RequestManager manager : managers) {
      manager.onTrimMemory(level);
    }
    // memory cache needs to be trimmed before bitmap pool to trim re-pooled Bitmaps too. See #687.
    memoryCache.trimMemory(level);
    bitmapPool.trimMemory(level);
    arrayPool.trimMemory(level);
  }

Glide中还会接收到onLowMemory方法回调,然后调用clearMemory()

  public void clearMemory() {
    // Engine asserts this anyway when removing resources, fail faster and consistently
    Util.assertMainThread();
    // memory cache needs to be cleared before bitmap pool to clear re-pooled Bitmaps too. See #687.
    memoryCache.clearMemory();
    bitmapPool.clearMemory();
    arrayPool.clearMemory();
  }

这里的目的就是清除缓存,防止OOM。

三、Glide源码解析

在Glide源码中,主要是依赖于Engine类来进行相应的缓存管理;通过GlideBuilder.build创建对应的Glide实例;而RequestManagerRetriever是Glide用来创建对应的生命周期管理的类,主要是创建对应的
RequestManager实例,并且通过Glide实例调用registerRequestManager方法添加到对应的List集合中。
在Glide中,Glide实例是单例的
Glide中,其实是采用了一个空的Fragment进行生命周期的管理和回调

1.Glide简单使用

Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);

2.Glide中的with方法

Glide的with流程.png

在Glide中,其with方法是多态的,可以传入不同的参数,这里不一一举例,就以下面的两个为例子:

  @NonNull
  public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
  }
  @NonNull
  public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
  }

其实Glide中的with方法的作用,就是通过RequestManagerRetriever实例获取到RequestManager生命周期管理类

(1)Glide#getRetriever()
  @NonNull
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    // 这里Context可能为null,造成的原因实际上是fragment发生错误而引起的
    Preconditions.checkNotNull(
        context,
        "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
            + "returns null (which usually occurs when getActivity() is called before the Fragment "
            + "is attached or after the Fragment is destroyed).");
    // 通过获取单例的Glide实例,调用非静态方法getRequestManagerRetriever
    // 获取RequestManagerRetriever实例对象
    return Glide.get(context).getRequestManagerRetriever();
  }
(2)Glide#get()

该方法主要的目的就是检查glide实例是否为null,如果为null就做初始化

  @NonNull
  public static Glide get(@NonNull Context context) {
    if (glide == null) {
      GeneratedAppGlideModule annotationGeneratedModule =
          getAnnotationGeneratedGlideModules(context.getApplicationContext());
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context, annotationGeneratedModule);
        }
      }
    }

    return glide;
  }
(3)Glide#checkAndInitializeGlide
  @GuardedBy("Glide.class")
  private static void checkAndInitializeGlide(
      @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
    // 如果正在初始化Glide,这里就抛出异常,可能是一个线程中可以有一个或者多个类进行初始化Glide的操作
    // 如果没有检查,可能会无限递归
    if (isInitializing) {
      throw new IllegalStateException(
          "You cannot call Glide.get() in registerComponents(),"
              + " use the provided Glide instance instead");
    }
    isInitializing = true;
    initializeGlide(context, generatedAppGlideModule);
    isInitializing = false;
  }
(4)Glide#initializeGlide

可以看出,该方法是具体执行初始化Glide实例的方法,主要是通过GlideBuilder构建者模式进行Glide实例的初始化

  @GuardedBy("Glide.class")
  @SuppressWarnings("deprecation")
  private static void initializeGlide(
      @NonNull Context context,
      @NonNull GlideBuilder builder,
      @Nullable GeneratedAppGlideModule annotationGeneratedModule) {
    Context applicationContext = context.getApplicationContext();
    List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
      manifestModules = new ManifestParser(applicationContext).parse();
    }

    if (annotationGeneratedModule != null
        && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
      Set<Class<?>> excludedModuleClasses = annotationGeneratedModule.getExcludedModuleClasses();
      Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
      while (iterator.hasNext()) {
        com.bumptech.glide.module.GlideModule current = iterator.next();
        if (!excludedModuleClasses.contains(current.getClass())) {
          continue;
        }
        if (Log.isLoggable(TAG, Log.DEBUG)) {
          Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
        }
        iterator.remove();
      }
    }

    if (Log.isLoggable(TAG, Log.DEBUG)) {
      for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
        Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
      }
    }
    // 创建RequestManagerRetriever.RequestManagerFactory,用于创建RequestManagerRetriever实例
    RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory()
            : null;
    builder.setRequestManagerFactory(factory);
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      module.applyOptions(applicationContext, builder);
    }
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
    // 创建Glide实例,在这里会调用Glide的构造器创建Glide实例
    // 并且会创建GlideContext实例,即Glide的上下文,在创建GlideContext上下文的时候
    // 会将Glide相关属性保存在GlideContext实例中,想要获取Glide中的相关属性
    // 则需要通过GlideContext获取,而GlideContext实例的获取,则需要通过Glide单例获取到
    Glide glide = builder.build(applicationContext);
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      try {
        module.registerComponents(applicationContext, glide, glide.registry);
      } catch (AbstractMethodError e) {
        throw new IllegalStateException(
            "Attempting to register a Glide v3 module. If you see this, you or one of your"
                + " dependencies may be including Glide v3 even though you're using Glide v4."
                + " You'll need to find and remove (or update) the offending dependency."
                + " The v3 module name is: "
                + module.getClass().getName(),
            e);
      }
    }
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
    }
    applicationContext.registerComponentCallbacks(glide);
    // 将Glide实例赋值给Glide中的静态变量
    Glide.glide = glide;
  }
(5)RequestManagerRetriever#get()

在Glide中,RequestManagerRetriever.get方法,也是有多种重载,这里我们主要看参数为Context、FragmentActivity、Fragment、Activity的几种

  @NonNull
  public RequestManager get(@NonNull Context context) {
    // 参数为Context的,其实都会根据Context的类型进行调用,一般都是调用到参数为Activity或者FragmentActivity的get方法
    // 如果这里的context==null,抛出异常
    if (context == null) {
      throw new IllegalArgumentException("You cannot start a load on a null Context");
    } else if (Util.isOnMainThread() && !(context instanceof Application)) {
      if (context instanceof FragmentActivity) {
        return get((FragmentActivity) context);
      } else if (context instanceof Activity) {
        return get((Activity) context);
      } else if (context instanceof ContextWrapper
          // Only unwrap a ContextWrapper if the baseContext has a non-null application context.
          // Context#createPackageContext may return a Context without an Application instance,
          // in which case a ContextWrapper may be used to attach one.
          && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
        return get(((ContextWrapper) context).getBaseContext());
      }
    }

    return getApplicationManager(context);
  }

  @NonNull
  public RequestManager get(@NonNull FragmentActivity activity) {
    // 如果Glide.with(context)这里的context是在子线程,那么就会获取到context.applicationContext
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      // 获取androidx.fragment.app.FragmentActivity中的SupportFragmentManager实例
      // 参数为FragmentActivity的,主要是针对androidx.fragment.app包下的
      FragmentManager fm = activity.getSupportFragmentManager();
      return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

  @NonNull
  public RequestManager get(@NonNull Fragment fragment) {
    Preconditions.checkNotNull(
        fragment.getContext(),
        "You cannot start a load on a fragment before it is attached or after it is destroyed");
    if (Util.isOnBackgroundThread()) {
      return get(fragment.getContext().getApplicationContext());
    } else {
      // 通过androidx.fragment.app.Fragment获取对应的ChildFragmentManager,其实与参数为FragmentActivity的类似
      FragmentManager fm = fragment.getChildFragmentManager();
      return supportFragmentGet(fragment.getContext(), fm, fragment, fragment.isVisible());
    }
  }

  @SuppressWarnings("deprecation")
  @NonNull
  public RequestManager get(@NonNull Activity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      // 如果参数为Activity的,则获取android.app包下的FragmentManager实例
      android.app.FragmentManager fm = activity.getFragmentManager();
      return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

在这里,参数为Fragment和FragmentActivity的,最终都是调用了RequestManagerRetriever.supportFragmentGet创建RequestManager实例;而参数为Activity的,最终是调用了RequestManagerRetriever.fragmentGet创建RequestManager实例。

(6)RequestManagerRetriever#supportFragmentGet和RequestManagerRetriever#fragmentGet
  @NonNull
  private RequestManager supportFragmentGet(
      @NonNull Context context,
      @NonNull FragmentManager fm,
      @Nullable Fragment parentHint,
      boolean isParentVisible) {
    // 创建一个空的Fragment,这个Fragment是继承自androidx.app.fragment.Fragment的
    // 在创建空的Fragment的时候,会创建对应的ActivityFragmentLifecycle生命周期回调
    // 然后该回调会在创建RequestManager的时候传入,并且将RequestManager作为监听器注册到ActivityFragmentLifecycle中
    // 而空的Fragment生命周期发生变化的时候,就会通过ActivityFragmentLifecycle调用对应的监听
    // 进而调用到对应的RequestManager中
    SupportRequestManagerFragment current =
        getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // 通过工厂模式创建RequestManager
      // 这个factory是在创建Glide实例的时候,创建RequestManagerRetriever实例的时候传入的
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }
  @SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
  @Deprecated
  @NonNull
  private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    // 创建一个空的Fragment,该Fragment是继承自android.app.Fragment的
    // 在创建空的Fragment的时候,会创建对应的ActivityFragmentLifecycle生命周期回调
    // 然后该回调会在创建RequestManager的时候传入,并且将RequestManager作为监听器注册到ActivityFragmentLifecycle中
    // 而空的Fragment生命周期发生变化的时候,就会通过ActivityFragmentLifecycle调用对应的监听
    // 进而调用到对应的RequestManager中
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // TODO(b/27524013): Factor out this Glide.get() call.
      Glide glide = Glide.get(context);
      // 通过工厂创建RequestManager
      // 这个factory是在创建Glide实例的时候,创建RequestManagerRetriever实例的时候传入的
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

从这里可以看出,在创建RequestManager生命周期管理类的时候,都创建了一个空的Fragment,而这个空的Fragment是通过添加给对应的页面的事务管理,与对应的页面做绑定,这样做的目的,是通过这个空的Fragment来在Glide内部做相应的生命周期管理,而不直接在对应的页面的生命周期做相应的操作,通过借助这个空的Fragment,实现在不同的生命周期的操作和回调。
在创建空的生命周期的时候,会创建ActivityFragmentLifecycle实例,而该实例会在创建RequestManager的时候传入到RequestManager中,并且在RequestManager中向ActivityFragmentLifecycle中注册一个监听回调,这样做的目的就是在空的Fragment生命周期发生变化的时候,通过调用ActivityFragmentLifecycle实例,进而调用注册的监听回调,最终回调给RequestManager,以达到RequestManager管理生命周期的目的。所以Glide的生命周期管理,其实主要是依赖于一个空的Fragment,通过加空的Fragment添加给对应的页面中,达到监听页面生命周期变化的目的,进而通知请求管理类RequestManager

(7)RequestManagerRetriever#getSupportRequestManagerFragment和RequestManagerRetriever#getRequestManagerFragment

这两个方法的内部实现基本类似,这里就只分析针对Activity获取RequestManagerFragment这个空的fragment的。
在这里需要调用handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();移除缓存map中的键值对,这样做的目的,是因为fragment在添加到事务,并且最后提交事务的时候,是根据handler.post发送一个提交事件来进行事务的提交的,但是handler发送出去的message并不能保证立刻执行,那么就需要保存临时缓存,通过临时缓存中的数据,判断fragment正在与fragmentManager进行绑定

  @SuppressWarnings("deprecation")
  @NonNull
  private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    // 这里第一次判断为null,是从HashMap中获取,
    // 如果创建对象之后,就立马加入到这个HashMap中
    // 这样第二次进入的时候,首先会去HashMap查找临时缓存的Fragment,可能这个Fragment还没有与FragmentManager绑定
    // 但是只要临时缓存中已经存在,则就不允许创建
    if (current == null) {
      current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
          current.getGlideLifecycle().onStart();
        }
        // 这里做一次缓存,其实就是为了保证一个Activity只有一个空白的Fragment
        pendingRequestManagerFragments.put(fm, current);
        // 这其实就是对应的事务提交,创建一个空的Fragment实例,提交给对应的Activity
        // 这里的内部实现其实也是通过Handler发送消息,处理提交任务,但是不能保证提交的任务会立马执行
        // 也不能保证提交的任务会在下一个任务进入的时候执行完成
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        // 当提交完成之后,通知移除pendingRequestManagerFragments这个Map集合中的键值对数据
        // 这样做的目的,其实也是为了让Handler中等待区域的消息马上进行工作
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }
(8)RequestManager中的生命周期回调

RequestManager对象的创建,是在Glide初始化的时候,调用RequestManagerRetriever的get方法的时候获取RequestManager对象时进行创建和初始化的。比如:androidx.fragment.app.fragment这个androidx目录下的Activity和Fragment的生命周期监听回调,就需要:
在创建SupportRequestManagerFragment对象的时候,其内部就会创建一个ActivityFragmentLifecycle对象,这就是Glide用来进行生命周期管理和回调的。
原理其实就是在使用Glide的时候,会在页面上创建一个空的Fragment,这个空的Fragment的生命周期是与当前页面一致的,而这个空的Fragment的生命周期在触发回调的时候就会调用ActivityFragmentLifecycle对象,进而调回调到RequestManager中。

  @NonNull
  private RequestManager supportFragmentGet(
      @NonNull Context context,
      @NonNull FragmentManager fm,
      @Nullable Fragment parentHint,
      boolean isParentVisible) {
    SupportRequestManagerFragment current =
        getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // TODO(b/27524013): Factor out this Glide.get() call.
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

首先看RequestManager的构造器,在这里会接收在RequestManagerRetriever中通过RequestManagerFactory工厂创建RequestManager实例的时候传入的一个Lifecycle实现类对象,即ActivityFragmentLifecycle实例,然后向其中注册监听,这里注册监听的时候传入this,是因为RequestManager实现了LifecycleListener接口,所以可以向ActivityFragmentLifecycle对象中注册监听接收回调,用于在空的Fragment的生命周期中进行回调

  RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    this.glide = glide;
    this.lifecycle = lifecycle;
    this.treeNode = treeNode;
    this.requestTracker = requestTracker;
    this.context = context;

    connectivityMonitor =
        factory.build(
            context.getApplicationContext(),
            new RequestManagerConnectivityListener(requestTracker));

    // If we're the application level request manager, we may be created on a background thread.
    // In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
    // issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
    // This should be entirely safe.
    if (Util.isOnBackgroundThread()) {
      mainHandler.post(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);

    defaultRequestListeners =
        new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
    setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());

    glide.registerRequestManager(this);
  }

比如ActivityFragmentLifecycle的onStart()实现:
就是由空的Fragment在onStart()生命周期中调用ActivityFragmentLifecycle的onStart(),然后遍历监听,进而调用到RequestManager中的onStart(),这个onStart()方法就是RequestManager实现了LifecycleListener接口之后重写的方法

  // ActivityFragmentLifecycle的onStart()
  // 由Glide中自定义的空的Fragment的onStart()中进行调用,ActivityFragmentLifecycle的onStart()在调用时
  // 就会遍历所有注册的LifecycleListener,这些LifecycleListener其实都是在RequestManager中注册
  // RequestManager中会有两部分的监听,一部分就是自身生命周期的
  // 一部分就是回调网络变化监听
  void onStart() {
    isStarted = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart();
    }
  }

而在RequestManager的实现了LifecycleListener接口实现onStart()方法如下:

  @Override
  public synchronized void onStart() {
    resumeRequests();
    targetTracker.onStart();
  }

这里的TargetTracker其实就是保存当前RequestManager中的Target集合,也就是当前RequestManager任务管理器管理的任务对应的目标的集合。
而对应的生命周期回调,就是让RequestManager执行对Request请求的不同的操作,然后让Target执行不同的操作,比如ImageViewTarget,就会判断是否有动画,在onStart的时候开始动画,在onStop的时候结束动画

3.RequestManager#load()

Glide的load流程.png

在RequestManager中load方法也是有多种重载,这里分析传入的参数为String,即图片路径的做法:

  @NonNull
  @CheckResult
  @Override
  public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }

这里asDrawable()其实就是传入一个Drawable类型,获取到对应的RequestBuilder实例。主要就是用于在RequestBuilder.into方法的时候使用。而RequestBuilder的load方法,其实就是做部分的属性初始化

4.RequestBuilder#into()

Glide_into.png
(1)RequestBuilder#into()

调用RequestBuilder的into()方法,最终都会调用这四个参数的这个into方法

  private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor) {
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    // 通过RequestBuilder获取构建一个Request实例
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
    // 这里相当于拿到上一个请求
    Request previous = target.getRequest();
    // 判断当前请求是否等价于上一个请求
    // 并且不跳过上一次请求的完成的内存缓存
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      // 如果请求已经完成,则重新开始,确保结果重新传递
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        // 使用上一个请求来执行,通过使用上一个请求进行请求的优化操作
        // 如果存在上一次的请求,则直接取出该请求,并且调用begin
        previous.begin();
      }
      return target;
    }
    // 清理掉目标请求管理
    requestManager.clear(target);
    // 将request设置给target中保存,以便下一次使用的时候取出
    target.setRequest(request);
    // 调用RequestManager的track来执行目标的Glide Request请求
    requestManager.track(target, request);

    return target;
  }

在调用into方法的时候,一般会传入ImageView,则返回一个ImageViewTarget。
其实就会调用GlideContext的buildImageViewTarget()
在这里,会调用requestManager.clear(target)其实这个调用的目的就是清楚该目标target中已经存在的request,然后只执行当前的request,不执行上一次的request

  // RequestManager.java
  public void clear(@Nullable final Target<?> target) {
    if (target == null) {
      return;
    }

    untrackOrDelegate(target);
  }

  private void untrackOrDelegate(@NonNull Target<?> target) {
    boolean isOwnedByUs = untrack(target);

    Request request = target.getRequest();
    if (!isOwnedByUs && !glide.removeFromManagers(target) && request != null) {
      target.setRequest(null);
      request.clear();
    }
  }
GlideContext#buildImageViewTarget()
  @NonNull
  public <X> ViewTarget<ImageView, X> buildImageViewTarget(
      @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
    // 调用工厂模式,根据transcodeClass生成对应的ImageViewTarget
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }
ImageViewTargetFactory#buildTarget
  public <Z> ViewTarget<ImageView, Z> buildTarget(
      @NonNull ImageView view, @NonNull Class<Z> clazz) {
    // 根据transcodeClass判断不同的类型的ImageViewTarget
    // 如果是调用asDrawable,则会创建DrawableImageViewTarget
    // 而Bitmap的则需要调用asBitmap才会执行
    if (Bitmap.class.equals(clazz)) {
      return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
    } else if (Drawable.class.isAssignableFrom(clazz)) {
      return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
    } else {
      throw new IllegalArgumentException(
          "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
    }
  }
DrawableImageViewTarget

这里其实就是继承ImageViewTarget,重写setResource函数,实现了显示在ImageView上显示Drawable图片的逻辑。

public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {

  public DrawableImageViewTarget(ImageView view) {
    super(view);
  }

  /** @deprecated Use {@link #waitForLayout()} instead. */
  // Public API.
  @SuppressWarnings({"unused", "deprecation"})
  @Deprecated
  public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {
    super(view, waitForLayout);
  }

  @Override
  protected void setResource(@Nullable Drawable resource) {
    view.setImageDrawable(resource);
  }
}
(2)RequestBuilder#buildRequest()

构建请求的过程,这里一般都是构建了SingleRequest实例。
只是想参数从RequestBuilder传入到SingleRequest中。

  private SingleRequest(
      Context context,
      GlideContext glideContext,
      @NonNull Object requestLock,
      @Nullable Object model,
      Class<R> transcodeClass,
      BaseRequestOptions<?> requestOptions,
      int overrideWidth,
      int overrideHeight,
      Priority priority,
      Target<R> target,
      @Nullable RequestListener<R> targetListener,
      @Nullable List<RequestListener<R>> requestListeners,
      RequestCoordinator requestCoordinator,
      Engine engine,
      TransitionFactory<? super R> animationFactory,
      Executor callbackExecutor) {
    this.requestLock = requestLock;
    this.context = context;
    this.glideContext = glideContext;
    this.model = model;
    this.transcodeClass = transcodeClass;
    this.requestOptions = requestOptions;
    this.overrideWidth = overrideWidth;
    this.overrideHeight = overrideHeight;
    this.priority = priority;
    this.target = target;
    this.targetListener = targetListener;
    this.requestListeners = requestListeners;
    this.requestCoordinator = requestCoordinator;
    this.engine = engine;
    this.animationFactory = animationFactory;
    this.callbackExecutor = callbackExecutor;
    status = Status.PENDING;

    if (requestOrigin == null && glideContext.isLoggingRequestOriginsEnabled()) {
      requestOrigin = new RuntimeException("Glide request origin trace");
    }
  }
(3)Request#begin()

这里是在RequestBuilder的into方法调用的时候,然后调用RequestManager.track方法,在RequestManager.track方法中,调用RequestTracker.runRequest方法

RequestTracker#runRequest
  public void runRequest(@NonNull Request request) {
    requests.add(request);
    // 判断是否暂停,if条件中就是没有暂停
    if (!isPaused) {
      // 这里其实就是调用了SingleRequest.begin方法
      request.begin();
    } else {
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
      pendingRequests.add(request);
    }
  }

其实就是调用SingleRequest#begin

  @Override
  public void begin() {
    synchronized (requestLock) {
      assertNotCallingCallbacks();
      stateVerifier.throwIfRecycled();
      startTime = LogTime.getLogTime();
      if (model == null) {
        // 检查外部调用的尺寸是否有效
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
          width = overrideWidth;
          height = overrideHeight;
        }
        // Only log at more verbose log levels if the user has set a fallback drawable, because
        // fallback Drawables indicate the user expects null models occasionally.
        // 失败回调
        int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
        onLoadFailed(new GlideException("Received null model"), logLevel);
        return;
      }

      if (status == Status.RUNNING) {
        throw new IllegalArgumentException("Cannot restart a running request");
      }

      // 如果是在Request请求完成之后重新启动,比如:adapter的notifyDataSetChanged操作
      // 这样的操作,通常会向同一个target或者View启动相同的请求,则可以使用上次获取的资源和大小
      // 而跳过重新请求
      if (status == Status.COMPLETE) {
        // 表示资源已经准备好,不需要网络请求,直接使用缓存资源
        onResourceReady(resource, DataSource.MEMORY_CACHE);
        return;
      }

      // 重新启动既未完成又未运行的请求可以视为新请求,并且可以从头开始重新运行。
      status = Status.WAITING_FOR_SIZE;
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        // 开始网络请求
        onSizeReady(overrideWidth, overrideHeight);
      } else {
        target.getSize(this);
      }

      if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
          && canNotifyStatusChanged()) {
        target.onLoadStarted(getPlaceholderDrawable());
      }
      if (IS_VERBOSE_LOGGABLE) {
        logV("finished run method in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }
(4)Request#onSizeReady

其实就是调用SingleRequest#onSizeReady

  @Override
  public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    synchronized (requestLock) {
      if (IS_VERBOSE_LOGGABLE) {
        logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
      if (status != Status.WAITING_FOR_SIZE) {
        return;
      }
      // 修改请求状态,改成正在执行请求
      status = Status.RUNNING;

      // 初始化可能请求的资源的大小
      float sizeMultiplier = requestOptions.getSizeMultiplier();
      this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
      this.height = maybeApplySizeMultiplier(height, sizeMultiplier);

      if (IS_VERBOSE_LOGGABLE) {
        logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
      }
      loadStatus =
          // 调用Engine.load方法加载请求资源
          engine.load(
              glideContext,
              model,
              requestOptions.getSignature(),
              this.width,
              this.height,
              requestOptions.getResourceClass(),
              transcodeClass,
              priority,
              requestOptions.getDiskCacheStrategy(),
              requestOptions.getTransformations(),
              requestOptions.isTransformationRequired(),
              requestOptions.isScaleOnlyOrNoTransform(),
              requestOptions.getOptions(),
              requestOptions.isMemoryCacheable(),
              requestOptions.getUseUnlimitedSourceGeneratorsPool(),
              requestOptions.getUseAnimationPool(),
              requestOptions.getOnlyRetrieveFromCache(),
              this,
              callbackExecutor);

      // This is a hack that's only useful for testing right now where loads complete synchronously
      // even though under any executor running on any thread but the main thread, the load would
      // have completed asynchronously.
      if (status != Status.RUNNING) {
        loadStatus = null;
      }
      if (IS_VERBOSE_LOGGABLE) {
        logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }
(5)Engine#load

在这里,就会优先去缓存中查找可用的数据

  public <R> LoadStatus load(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor) {
    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
    // 拿到缓存或者请求的key
    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);

    EngineResource<?> memoryResource;
    synchronized (this) {
      // 加载缓存中的数据,主要是从ActiveResources和MemoryCache
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);

      if (memoryResource == null) {
        // 如果ActiveResources和MemoryCache两个缓存中的数据为null
        // 那么调用waitForExistingOrStartNewJob方法
        return waitForExistingOrStartNewJob(
            glideContext,
            model,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            options,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache,
            cb,
            callbackExecutor,
            key,
            startTime);
      }
    }

    // Avoid calling back while holding the engine lock, doing so makes it easier for callers to
    // deadlock.
    // 如果内存缓存Lru中资源存在,则回调使用
    cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
    return null;
  }
(6)Engine#loadFromMemory
  @Nullable
  private EngineResource<?> loadFromMemory(
      EngineKey key, boolean isMemoryCacheable, long startTime) {
    // 判断是否使用缓存,如果不使用,则直接return
    if (!isMemoryCacheable) {
      return null;
    }
    // 从ActiveResources中加载,ActiveResources可以认为是活动缓存
    // 即正在使用的资源缓存
    EngineResource<?> active = loadFromActiveResources(key);
    if (active != null) {
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from active resources", startTime, key);
      }
      return active;
    }

    // 从MemoryCache缓存中加载资源
    EngineResource<?> cached = loadFromCache(key);
    if (cached != null) {
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from cache", startTime, key);
      }
      return cached;
    }

    return null;
  }
(7)Engine#loadFromActiveResources和Engine#loadFromCache

Glide在从缓存中取数据的时候,如果在活动缓存中存在资源,则直接返回;如果在活动缓存中不存在资源,但是在内存缓存中存在资源,而内存缓存中是采用LruCache,那么就会调用其remove方法返回对应的缓存数据,然后加入到活动缓存中,这样内存缓存中就不存在缓存数据。
为什么有了内存缓存,还需要一个活动缓存呢?主要原因就是内存缓存是有长度限制的,当应用中正在使用的资源数达到内存缓存的最大容量时,如果此时又有一个新的资源被使用,加入到内存缓存,则内存缓存中就会移除最近最久未使用的资源,那么当前正在被使用的资源中就会出现一个成了null,从而导致空指针问题。
如果是磁盘缓存,则需要在对应的执行器比如DataCacheGenerator.startNext中进行处理。
获取不同的执行器,如果是有缓存的,则会使用对应的缓存策略执行器,然后在其缓存策略中调用helper.getDiskCache().get(originalKey)获取磁盘缓存中的数据。这里的helper其实就是DecodeHelper。而DecodeHelper.getDiskCache()其实就是调用diskCacheProvider.getDiskCache(),而DiskCache是一个接口,其实现类是DiskLruCacheWrapper,所以也就是调用DiskLruCacheWrapper的get()方法返回磁盘缓存中的File文件

  @Nullable
  private EngineResource<?> loadFromActiveResources(Key key) {
    // 从ActiveResources中取出正在使用的资源缓存
    EngineResource<?> active = activeResources.get(key);
    // 如果该资源不为null,则计数+1,表示有增加一个正在使用的
    if (active != null) {
      active.acquire();
    }

    return active;
  }
  private EngineResource<?> loadFromCache(Key key) {
    // 从MemoryCache内存缓存中取出key对应的资源
    // 而MemoryCache中缓存的资源,是在EngineResource被释放的时候调用MemoryCache的put方法放入
    EngineResource<?> cached = getEngineResourceFromCache(key);
    // 如果该资源不为null,则使用计数加1
    if (cached != null) {
      cached.acquire();
      // 并且将资源从MemoryCache中取出加入到ActiveResources中
      activeResources.activate(key, cached);
    }
    return cached;
  }

  private EngineResource<?> getEngineResourceFromCache(Key key) {
    // 移除MemoryCache中的资源,并且将该资源返回
    Resource<?> cached = cache.remove(key);

    final EngineResource<?> result;
    if (cached == null) {
      result = null;
    } else if (cached instanceof EngineResource) {
      // Save an object allocation if we've cached an EngineResource (the typical case).
      result = (EngineResource<?>) cached;
    } else {
      result =
          new EngineResource<>(
              cached, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ true, key, /*listener=*/ this);
    }
    return result;
  }
(8)Engine#waitForExistingOrStartNewJob
  private <R> LoadStatus waitForExistingOrStartNewJob(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor,
      EngineKey key,
      long startTime) {

    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb, callbackExecutor);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }
    // 如果ActiveResources和MemoryCache两个缓存中的数据为null
    // 则创建EngineJob和DecodeJob,DecodeJob是解码的,
    // 用于从缓存的数据或原始源解码资源,并应用转换和转码。
    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);
    // 初始化decodeJob,这里会对DecodeJob中的runReason赋值为RunReason.INITIALIZE
    DecodeJob<R> decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);

    jobs.put(key, engineJob);

    engineJob.addCallback(cb, callbackExecutor);
    // 开始对磁盘缓存或者原始数据进行解码操作
    engineJob.start(decodeJob);

    if (VERBOSE_IS_LOGGABLE) {
      logWithTimeAndKey("Started new load", startTime, key);
    }
    return new LoadStatus(cb, engineJob);
  }
(9)EngineJob#start
  public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor =
        decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
    executor.execute(decodeJob);
  }
(10)DecodeJob#willDecodeFromCache
  boolean willDecodeFromCache() {
    Stage firstStage = getNextStage(Stage.INITIALIZE);
    return firstStage == Stage.RESOURCE_CACHE || firstStage == Stage.DATA_CACHE;
  }
(11)GlideExecutor#execute

在EngineJob的start方法中执行。因为DecodeJob是实现了Runnable接口,所以这里就是执行DecodeJob的run方法

executor.execute(decodeJob);
(12)DecodeJob#run()
  @Override
  public void run() {
    // This should be much more fine grained, but since Java's thread pool implementation silently
    // swallows all otherwise fatal exceptions, this will at least make it obvious to developers
    // that something is failing.
    GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
    // Methods in the try statement can invalidate currentFetcher, so set a local variable here to
    // ensure that the fetcher is cleaned up either way.
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      // 是否取消了当前请求
      if (isCancelled) {
        notifyFailed();
        return;
      }
      runWrapped();
    } catch (CallbackException e) {
      // If a callback not controlled by Glide throws an exception, we should avoid the Glide
      // specific debug logic below.
      throw e;
    } catch (Throwable t) {
      // Catch Throwable and not Exception to handle OOMs. Throwables are swallowed by our
      // usage of .submit() in GlideExecutor so we're not silently hiding crashes by doing this. We
      // are however ensuring that our callbacks are always notified when a load fails. Without this
      // notification, uncaught throwables never notify the corresponding callbacks, which can cause
      // loads to silently hang forever, a case that's especially bad for users using Futures on
      // background threads.
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(
            TAG,
            "DecodeJob threw unexpectedly" + ", isCancelled: " + isCancelled + ", stage: " + stage,
            t);
      }
      // When we're encoding we've already notified our callback and it isn't safe to do so again.
      if (stage != Stage.ENCODE) {
        throwables.add(t);
        notifyFailed();
      }
      if (!isCancelled) {
        throw t;
      }
      throw t;
    } finally {
      // Keeping track of the fetcher here and calling cleanup is excessively paranoid, we call
      // close in all cases anyway.
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }
(13)DecodeJob#runWrapped()

初始时,runReason的值是RunReason.INITIALIZE,是在DecodeJob的init方法中初始化赋值。

  private void runWrapped() {
    switch (runReason) {
      // 第一次请求,先初始化
      case INITIALIZE:
        // 获取资源状态
        stage = getNextStage(Stage.INITIALIZE);
        // 根据当前资源状态,获取资源执行器
        // 这里什么都没有配置,所以返回的就是SourceGenerator
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }
(14)DecodeJob#getNextStage

在Glide中,其默认的缓存策略是DiskCacheStrategy.AUTOMATIC,也就是decodeCachedResource()会返回true,那么其stage就是Stage.RESOURCE_CACHE,所以默认使用的执行器ResourceCacheGenerator

  private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
        // 如果外部调用配置了资源缓存策略,那么返回Stage.RESOURCE_CACHE
        // 否则继续调用Stage.RESOURCE_CACHE执行
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE
            : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
        //如果外部配置了源数据缓存,那么返回 Stage.DATA_CACHE 
        //否则继续调用 getNextStage(Stage.DATA_CACHE)
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE
            : getNextStage(Stage.DATA_CACHE);
      case DATA_CACHE:
        // Skip loading from source if the user opted to only retrieve the resource from cache.
        //如果只能从缓存中获取数据,则直接返回 FINISHED,否则,返回SOURCE。         
        //意思就是一个新的资源
        return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
      case SOURCE:
      case FINISHED:
        return Stage.FINISHED;
      default:
        throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
  }
(15)DecodeJob#getNextGenerator

获取不同的执行器,如果是有缓存的,则会使用对应的缓存策略执行器,然后在其缓存策略中调用helper.getDiskCache().get(originalKey)获取磁盘缓存中的数据。这里的helper其实就是DecodeHelper。而DecodeHelper.getDiskCache()其实就是调用diskCacheProvider.getDiskCache(),而DiskCache是一个接口,其实现类是DiskLruCacheWrapper,所以也就是调用DiskLruCacheWrapper的get()方法返回磁盘缓存中的File文件

  private DataFetcherGenerator getNextGenerator() {
    switch (stage) {
      // 从资源缓存执行器。具体的选择,看(14)步。Glide默认是选择ResourceCacheGenerator
      case RESOURCE_CACHE:
        return new ResourceCacheGenerator(decodeHelper, this);
      // 源数据磁盘缓存执行器
      case DATA_CACHE:
        return new DataCacheGenerator(decodeHelper, this);
      // 什么都没有配置,源数据的执行器
      case SOURCE:
        return new SourceGenerator(decodeHelper, this);
      case FINISHED:
        return null;
      default:
        throw new IllegalStateException("Unrecognized stage: " + stage);
    }
  }

这里什么都没有配置,所以返回的就是SourceGenerator

(16)DecodeJob#runGenerators
  private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    // 判断是否取消,是否开始
    // 调用DataFetcherGenerator.startNext()判断是否是属于开始执行的任务
    // 如果是什么都没有配置,其实就是调用SourceGenerator.startNext()
    while (!isCancelled
        && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }
    // We've run out of stages and generators, give up.
    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
      notifyFailed();
    }

    // Otherwise a generator started a new load and we expect to be called back in
    // onDataFetcherReady.
  }
(17)SourceGenerator#startNext()
  @Override
  public boolean startNext() {
    if (dataToCache != null) {
      Object data = dataToCache;
      dataToCache = null;
      cacheData(data);
    }

    if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
      return true;
    }
    sourceCacheGenerator = null;

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      // 获取一个ModeLoader加载器
      loadData = helper.getLoadData().get(loadDataListIndex++);
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
              || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;
        startNextLoad(loadData);
      }
    }
    return started;
  }
  private void startNextLoad(final LoadData<?> toStart) {
    // 使用加载器中的fetcher根据优先级加载数据
    loadData.fetcher.loadData(
        helper.getPriority(),
        new DataCallback<Object>() {
          @Override
          public void onDataReady(@Nullable Object data) {
            if (isCurrentRequest(toStart)) {
              onDataReadyInternal(toStart, data);
            }
          }

          @Override
          public void onLoadFailed(@NonNull Exception e) {
            if (isCurrentRequest(toStart)) {
              onLoadFailedInternal(toStart, e);
            }
          }
        });
  }
因为默认的是使用ResourceCacheGenerator执行器,所以这里做一个对比:

其实ResourceCacheGenerator相对于SourceGenerator执行器,就是多出一步在请求网络之前,优先请求缓存的步骤。

  public boolean startNext() {
    List<Key> sourceIds = helper.getCacheKeys();
    if (sourceIds.isEmpty()) {
      return false;
    }
    List<Class<?>> resourceClasses = helper.getRegisteredResourceClasses();
    if (resourceClasses.isEmpty()) {
      if (File.class.equals(helper.getTranscodeClass())) {
        return false;
      }
      throw new IllegalStateException(
          "Failed to find any load path from "
              + helper.getModelClass()
              + " to "
              + helper.getTranscodeClass());
    }
    while (modelLoaders == null || !hasNextModelLoader()) {
      resourceClassIndex++;
      if (resourceClassIndex >= resourceClasses.size()) {
        sourceIdIndex++;
        if (sourceIdIndex >= sourceIds.size()) {
          return false;
        }
        resourceClassIndex = 0;
      }

      Key sourceId = sourceIds.get(sourceIdIndex);
      Class<?> resourceClass = resourceClasses.get(resourceClassIndex);
      Transformation<?> transformation = helper.getTransformation(resourceClass);

      currentKey =
          new ResourceCacheKey( // NOPMD AvoidInstantiatingObjectsInLoops
              helper.getArrayPool(),
              sourceId,
              helper.getSignature(),
              helper.getWidth(),
              helper.getHeight(),
              transformation,
              resourceClass,
              helper.getOptions());
      // 从磁盘缓存中获取数据
      cacheFile = helper.getDiskCache().get(currentKey);
      if (cacheFile != null) {
        sourceKey = sourceId;
        modelLoaders = helper.getModelLoaders(cacheFile);
        modelLoaderIndex = 0;
      }
    }

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      // 如果有缓存存在,则会更新modelLoaders,而不会使用之前的。如果是没有缓存
      // 这里应该是会继续根据RequestManager.load方法传入的参数取出对应的Loader
      ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
      loadData =
          modelLoader.buildLoadData(
              cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
      if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
        started = true;
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }

    return started;
  }
(18)DecodeHelper#getLoadData()
  List<LoadData<?>> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
      // 根据从Glide注册的Model来获取加载器(注册是在Glide初始化的时候通过registry.append()添加的)
      List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
      //noinspection ForLoopReplaceableByForEach to improve perf
      for (int i = 0, size = modelLoaders.size(); i < size; i++) {
        ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
        // 开始构建加载器
        LoadData<?> current = modelLoader.buildLoadData(model, width, height, options);
        // 如果加载器不为空,那么添加进临时缓存
        if (current != null) {
          loadData.add(current);
        }
      }
    }
    return loadData;
  }

这里首先会拿到一个加载器的容器,加载器是在Glide初始化的时候通过Registry.append()添加的,这里如果是不使用缓存的,而是直接用Http请求,那么ModelLoad的实现类是HttpGlideUrlLoader加载器。

(19)HttpGlideUrlLoader#buildLoadData()
  @Override
  public LoadData<InputStream> buildLoadData(
      @NonNull GlideUrl model, int width, int height, @NonNull Options options) {
    // GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time
    // spent parsing urls.
    GlideUrl url = model;
    if (modelCache != null) {
      url = modelCache.get(model, 0, 0);
      if (url == null) {
        modelCache.put(model, 0, 0, model);
        url = model;
      }
    }
    int timeout = options.get(TIMEOUT);
    // 这里就是创建一个HttpUrlFetcher对象给加载器
    return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
  }

通过这里可以知道,如果是网络请求图片,那么加载器中的fetcher对象,其实就是HttpUrlFetcher对象。这里获取到ModeLoader加载器之后,返回继续调用(17)步中的loadData.fetcher.loadData调用。然后就是调用到了HttpUrlFetcher.loadData方法。

(20)HttpUrlFetcher#loadData()
  @Override
  public void loadData(
      @NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
    long startTime = LogTime.getLogTime();
    try {
      // http请求,返回一个InputStream输入流
      // 这里内部其实就是调用UrlConnection请求网络
      InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
      // 将InputStream输入流通过callback回调返回
      // TODO:具体看(17)步中的回调,其实就是调用了SourceGenerator.onDataReadyInternal方法
      callback.onDataReady(result);
    } catch (IOException e) {
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "Failed to load data for url", e);
      }
      callback.onLoadFailed(e);
    } finally {
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }
(21)SourceGenerator.onDataReadyInternal
  void onDataReadyInternal(LoadData<?> loadData, Object data) {
    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
      dataToCache = data;
      // We might be being called back on someone else's thread. Before doing anything, we should
      // reschedule to get back onto Glide's thread.
      cb.reschedule();
    } else {
      // 如果不使用缓存,则会调用else
      // 这里就是回调到了DecodeJob的方法
      cb.onDataFetcherReady(
          loadData.sourceKey,
          data,
          loadData.fetcher,
          loadData.fetcher.getDataSource(),
          originalKey);
    }
  }
(22)DecodeJob#onDataFetcherReady
  @Override
  public void onDataFetcherReady(
      Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
    // 当前返回数据的key
    this.currentSourceKey = sourceKey;
    // 网络请求返回的数据
    this.currentData = data;
    // 返回数据的执行器,如果是网络请求,则就是HttpUrlFetcher对象
    this.currentFetcher = fetcher;
    // 数据来源,其实就是网络来源,URL
    this.currentDataSource = dataSource;
    this.currentAttemptingKey = attemptedKey;
    if (Thread.currentThread() != currentThread) {
      runReason = RunReason.DECODE_DATA;
      callback.reschedule(this);
    } else {
      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
      try {
        // 解析返回回来的数据
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }
(23)DecodeJob#decodeFromRetrievedData
  private void decodeFromRetrievedData() {
    ...
    Resource<R> resource = null;
    try {
      // 调用decodeFrom解析数据,HttpUrlFetcher、InputStream、currentDataSource
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    // 解析完成,通知下去
    if (resource != null) {
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }

而解析的过程,最终就会调用LoadPath.load方法

(24)LoadPath#load

最终解析数据的,其实是LoadPath的decode方法

  public Resource<Transcode> load(
      DataRewinder<Data> rewinder,
      @NonNull Options options,
      int width,
      int height,
      DecodePath.DecodeCallback<ResourceType> decodeCallback)
      throws GlideException {
    List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
    try {
      return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
    } finally {
      listPool.release(throwables);
    }
  }
// DecodePath.java
  public Resource<Transcode> decode(
      DataRewinder<DataType> rewinder,
      int width,
      int height,
      @NonNull Options options,
      DecodeCallback<ResourceType> callback)
      throws GlideException {
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
    // 解析完成后的数据回调出去
    // 这里是回调到DecodeJob的onResourceDecoded方法
    Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
    // 转换资源为目标资源(Bitmap to Drawable)
    return transcoder.transcode(transformed, options);
  }

而这里最终就会调用decoder.decode,decoder就是调用了StreamBitmapDecoder。而这里需要考虑一个情况,就是ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);为什么最终会得到的是一个StreamBitmapDecoder,因为网络请求得到的是一个InputStream,而这个时候就需要解析数据得到对应的对象,而Glide里,其实InputStream只能解析转成Git或者Bitmap,如果是需要的图片,而不是动图,就是获取到Bitmap。具体可以根据StreamBitmapDecoder的类定义知道。ResourceDecoder的第一个泛型是数据源类型,第二个泛型是目标类型

public class StreamBitmapDecoder implements ResourceDecoder<InputStream, Bitmap> {
...
}
(25)StreamBitmapDecoder#decode

这里就是最终数据压缩采样,然后在完成之后,就会继续回到DecodePath的decode方法,调用其最终return的时候transcoder.transcode(transformed, options);

  @Override
  public Resource<Bitmap> decode(
      @NonNull InputStream source, int width, int height, @NonNull Options options)
      throws IOException {

    // Use to fix the mark limit to avoid allocating buffers that fit entire images.
    final RecyclableBufferedInputStream bufferedStream;
    final boolean ownsBufferedStream;
    ...
    try {
      // 根据请求配置来对数据进行采样压缩,获取一个Resource<Bitmap>
      return downsampler.decode(invalidatingStream, width, height, options, callbacks);
    } finally {
      ...
    }
  }
(26)DecodeJob#onResourceDecoded

这里是在(24)步中调用callback.onResourceDecoded(decoded);回调回来的

  <Z> Resource<Z> onResourceDecoded(DataSource dataSource, @NonNull Resource<Z> decoded) {
    // 获取资源类型
    @SuppressWarnings("unchecked")
    Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
    Transformation<Z> appliedTransformation = null;
    Resource<Z> transformed = decoded;
    // 如果不是从磁盘资源中获取需要进行transform操作
    if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
      appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
      transformed = appliedTransformation.transform(glideContext, decoded, width, height);
    }
    ...
    // 构建数据编码的策略
    final EncodeStrategy encodeStrategy;
    final ResourceEncoder<Z> encoder;
    if (decodeHelper.isResourceEncoderAvailable(transformed)) {
      encoder = decodeHelper.getResultEncoder(transformed);
      encodeStrategy = encoder.getEncodeStrategy(options);
    } else {
      encoder = null;
      encodeStrategy = EncodeStrategy.NONE;
    }
    // 根据编码策略,构建缓存key
    Resource<Z> result = transformed;
    boolean isFromAlternateCacheKey = !decodeHelper.isSourceKey(currentSourceKey);
    if (diskCacheStrategy.isResourceCacheable(
        isFromAlternateCacheKey, dataSource, encodeStrategy)) {
      if (encoder == null) {
        throw new Registry.NoResultEncoderAvailableException(transformed.get().getClass());
      }
      final Key key;
      switch (encodeStrategy) {
        case SOURCE:
          key = new DataCacheKey(currentSourceKey, signature);
          break;
        case TRANSFORMED:
          key =
              new ResourceCacheKey(
                  decodeHelper.getArrayPool(),
                  currentSourceKey,
                  signature,
                  width,
                  height,
                  appliedTransformation,
                  resourceSubClass,
                  options);
          break;
        default:
          throw new IllegalArgumentException("Unknown strategy: " + encodeStrategy);
      }
      // 初始化编码管理者,用于提交到内存缓存中
      LockedResource<Z> lockedResult = LockedResource.obtain(transformed);
      deferredEncodeManager.init(key, encoder, lockedResult);
      result = lockedResult;
    }
    return result;
  }
(27)BitmapDrawableTranscoder#transcode

转换完成之后,就会继续回到了DecodeJob的decodeFromRetrievedData,因为这里是在网络请求之后,调用DecodeJob的decodeFromData方法解析数据,在解析完成之后,就需要通知回去。所以这里回到第(23)步,继续调用notifyEncodeAndRelease()

  public Resource<BitmapDrawable> transcode(
      @NonNull Resource<Bitmap> toTranscode, @NonNull Options options) {
    return LazyBitmapDrawableResource.obtain(resources, toTranscode);
  }
(28)DecodeJob#notifyEncodeAndRelease

这里主要就是将数据返回到应用中,用于在应用中显示,并且保存在活动缓存中。然后会通过调用DiskLruCache保存网络请求到的图片数据到磁盘中。

  private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    if (resource instanceof Initializable) {
      ((Initializable) resource).initialize();
    }

    Resource<R> result = resource;
    LockedResource<R> lockedResource = null;
    if (deferredEncodeManager.hasResourceToEncode()) {
      lockedResource = LockedResource.obtain(resource);
      result = lockedResource;
    }
    // 通知上层,进行数据显示和活动缓存处理
    notifyComplete(result, dataSource);

    stage = Stage.ENCODE;
    try {
      // TODO:如果有资源需要进行编码,这里其实就是将数据通过DiskLruCache保存在磁盘中
      if (deferredEncodeManager.hasResourceToEncode()) {
        deferredEncodeManager.encode(diskCacheProvider, options);
      }
    } finally {
      if (lockedResource != null) {
        lockedResource.unlock();
      }
    }
    // Call onEncodeComplete outside the finally block so that it's not called if the encode process
    // throws.
    onEncodeComplete();
  }
    // DeferredEncodeManager类是DecodeJob的内部类
    // 这里的diskCacheProvider是在Engine对象创建的时候,保存在DecodeJobFactory中
    void encode(DiskCacheProvider diskCacheProvider, Options options) {
      GlideTrace.beginSection("DecodeJob.encode");
      try {
        diskCacheProvider
            .getDiskCache()
            .put(key, new DataCacheWriter<>(encoder, toEncode, options));
      } finally {
        toEncode.unlock();
        GlideTrace.endSection();
      }
    }
(29)EngineJob#notifyCallbacksOfResult

在经过DecodeJob的notifyEncodeAndRelease()通知回调之后,经过一系列的调用,就会执行到EngineJob的notifyCallbacksOfResult()

  void notifyCallbacksOfResult() {
    ResourceCallbacksAndExecutors copy;
    Key localKey;
    EngineResource<?> localResource;
    synchronized (this) {
      stateVerifier.throwIfRecycled();
      if (isCancelled) {
        // 此时如果请求被取消,则释放资源,返回,不显示结果
        resource.recycle();
        release();
        return;
      } else if (cbs.isEmpty()) {
        throw new IllegalStateException("Received a resource without any callbacks to notify");
      } else if (hasResource) {
        throw new IllegalStateException("Already have resource");
      }
      engineResource = engineResourceFactory.build(resource, isCacheable, key, resourceListener);
      hasResource = true;
      copy = cbs.copy();
      incrementPendingCallbacks(copy.size() + 1);

      localKey = key;
      localResource = engineResource;
    }
    // 回调上层Engine,任务完成
    // 这里就是完成的一些处理,包括将结果添加到活动缓存中
    engineJobListener.onEngineJobComplete(this, localKey, localResource);
    // 遍历资源,回调给ImageViewTarget
    for (final ResourceCallbackAndExecutor entry : copy) {
      // CallResourceReady是EngineJob的内部类,是一个Runnable的实现类
      entry.executor.execute(new CallResourceReady(entry.cb));
    }
    decrementPendingCallbacks();
  }
(30)CallResourceReady#callCallbackOnResourceReady

在执行CallResourceReady任务的时候,就会调用EngineJob的callCallbackOnResourceReady方法回调结果

  @Synthetic
  @GuardedBy("this")
  void callCallbackOnResourceReady(ResourceCallback cb) {
    try {
      // 这个就是回调到了Request,也就是SingleRequest中
      cb.onResourceReady(engineResource, dataSource);
    } catch (Throwable t) {
      throw new CallbackException(t);
    }
  }

相关文章

网友评论

      本文标题:Android-Glide源码解析

      本文链接:https://www.haomeiwen.com/subject/knxytktx.html