Glide 源码解析与原理总结——Glide.with

写作背景

Glide 作为著名的图片加载框架,几乎每一个项目都使用到。笔者尝试通过别人的博客来了解 Glide 原理,但是每次都是看着看着就懵逼了,不是因为别人写的不好,而是 Glide 实在是太复杂了,于是决定自己撸一遍,加深印象。纸上得来终觉浅,绝知此事要躬行。

因为 Glide 太庞大了,做不到面面俱到,所以笔者主要先梳理主干核心原理,后续持续整理。本文源码分析基于4.15.0,就从最基础的调用 Glide.with(context).load(url).into(imageView) 来入手,把主流程最核心的源码整理并且标注、总结。

该篇是Glide.with

Glide.with 源码分析

|-------------------------------|--------------------|
| 类 | 作用 |
| Glide | 负责线程池、缓存的构建 |
| RequestManagerRetriever | 负责获取RequestManager |
| SupportRequestManagerFragment | 用户接收和转发生命周期 |
| RequestManager | 用于请求管理 |

第1步,从 Glide.with 出发,可以看到Glide.with 有很多重载方法,目的是返回一个RequestManager。(Glide.java)

java 复制代码
  
  //传递Context
  public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }

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

  // 传递Fragment
  public static RequestManager with(@NonNull Fragment fragment) {
    return getRetriever(fragment.getContext()).get(fragment);
  }

  //传递View
  public static RequestManager with(@NonNull View view) {
    return getRetriever(view.getContext()).get(view);
  }

......

第2步 Glide.with 里面会调用 getRetriever方法,getRetriever() 先会调用 Glide.get(),Glide.get 会调用checkAndInitializeGlide 方法,注意会传递一个APT生成的 GeneratedAppGlideModuleImpl(Glide.java)

java 复制代码
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    // 省略...
    return Glide.get(context).getRequestManagerRetriever();
  }
  //双层检测单例模式
  public static Glide get(@NonNull Context context) {
    if (glide == null) {
      //getAnnotationGeneratedGlideModules 内部通过。 
     //Class.forName("com.bumptech.glide.GeneratedAppGlideModuleImpl")
    //拿到GeneratedAppGlideModuleImpl 并且作为参数传递
      GeneratedAppGlideModule annotationGeneratedModule =
          getAnnotationGeneratedGlideModules(context.getApplicationContext());
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context, annotationGeneratedModule);
        }
      }
    }
    return glide;
  }
 
  

最终来到Glide.initializeGlide,GeneratedAppGlideModuleImpl 的作用先记录,后续再慢慢了解,因为 Glide 内容实在太庞大了,每一个细节都要掌握无法梳理主流程(Glide.java)

java 复制代码
  private static void initializeGlide(
      @NonNull Context context,
      @NonNull GlideBuilder builder,
      @Nullable GeneratedAppGlideModule annotationGeneratedModule) {
    //1. 获取应用AppContext,最终是用来构建Glide的
    Context applicationContext = context.getApplicationContext();
    //2.这里通过传递进来的 GeneratedAppGlideModuleImpl 调用 getExcludedModuleClasses
    List<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<GlideModule> iterator = manifestModules.iterator();
      while (iterator.hasNext()) {
        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 (GlideModule glideModule : manifestModules) {
        Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
      }
    }

    //3.这里通过传递进来的 GeneratedAppGlideModuleImpl 获取 RequestManagerRetriever.RequestManagerFactory
    RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory()
            : null;
    //4.将拿到的工厂添加到GlideBuilder
    builder.setRequestManagerFactory(factory);
    for (GlideModule module : manifestModules) {
      module.applyOptions(applicationContext, builder);
    }
    //5.这里通过传递进来的 GeneratedAppGlideModuleImpl 调用 applyOptions
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
    //6.通过GlideBuilder 建造者模式生成 Glide
    Glide glide = builder.build(applicationContext, manifestModules, annotationGeneratedModule);
    applicationContext.registerComponentCallbacks(glide);
    //7. 将构建出来的glide 赋值给 Glide 的静态变量
    Glide.glide = glide;
  }

第3步,我们看到了有一个GlideBuilder 来生成Glide,这里有一个地方非常关键:GliderBuilder 来构建Glide,传递的Context 是applicationContext!!!, 你外部使用activity, 这里都会getApplicationContext 传入!!!

java 复制代码
  Glide build(
      @NonNull Context context,
      List<GlideModule> manifestModules,
      AppGlideModule annotationGeneratedGlideModule) {
    //实例化网络请求线程池
    if (sourceExecutor == null) {
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }

    //实例化磁盘缓存线程池
    if (diskCacheExecutor == null) {
      diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }

    //实例化图片加载动画线程池
    if (animationExecutor == null) {
      animationExecutor = GlideExecutor.newAnimationExecutor();
    }

    //实例化图片加载内存大小计算器
    if (memorySizeCalculator == null) {
      memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
    }

    //实例化网络连接监控工厂
    if (connectivityMonitorFactory == null) {
      connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
    }

    //实例化Bitmap对象池
    if (bitmapPool == null) {
      int size = memorySizeCalculator.getBitmapPoolSize();
      if (size > 0) {
        bitmapPool = new LruBitmapPool(size);
      } else {
        bitmapPool = new BitmapPoolAdapter();
      }
    }
    //实例化数组对象池
    if (arrayPool == null) {
      arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
    }
    //实例化内存缓存 LruCache
    if (memoryCache == null) {
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }
    //实例化磁盘缓存工厂
    if (diskCacheFactory == null) {
      diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }
    //构建执行缓存策略跟线程池的引擎
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              animationExecutor,
              isActiveResourceRetentionAllowed);
    }

    if (defaultRequestListeners == null) {
      defaultRequestListeners = Collections.emptyList();
    } else {
      defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
    }

    GlideExperiments experiments = glideExperimentsBuilder.build();
    //实例化RequestManagerRetriever 请求管理类
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);

    //实例化Glide
    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptionsFactory,
        defaultTransitionOptions,
        defaultRequestListeners,
        manifestModules,
        annotationGeneratedGlideModule,
        experiments);
  }

第4步,所以首次调用 Glide.get() 会把 Glide 构建完成,那么调用 Glide 的 getRequestManagerRetriver()就能拿到 RequestManagerRetriver对象。下面看看RequestManagerRetriver.get() 方法,也是有很多重载方法。

先看下RequestManagerRetriver.get(Context context), 可以看到如果不在主线程或者Context为AppContext,那么调用的是getApplicationManager

java 复制代码
  @NonNull
  public RequestManager get(@NonNull Context context) {
    if (context == null) {
      throw new IllegalArgumentException("You cannot start a load on a null Context");
    } else if (Util.isOnMainThread() && !(context instanceof Application)) {//1.主线程并且context不为Application
      if (context instanceof FragmentActivity) {
        //2.如果是FragmentActivity
        return get((FragmentActivity) context);
      } else if (context instanceof Activity) {
        //3.如果是Activity
        return get((Activity) context);
      } else if (context instanceof ContextWrapper
          && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
        //4.如果是ContextWrapper,并且baseContext的AppContext 不为空
        return get(((ContextWrapper) context).getBaseContext());
      }
    }
    //5.不在主线程或者context为AppContext 调用getApplicationManager
    return getApplicationManager(context);
  }

第5步,先看getApplicationManager(context) 构建applicationManager的对象, 这个是App层级的RequestManager。 (RequestManagerReceiver.java)

java 复制代码
  private RequestManager getApplicationManager(@NonNull Context context) {
    // Either an application context or we're on a background thread.
    if (applicationManager == null) {
      synchronized (this) {
        if (applicationManager == null) {
          //使用AppContext 作为参数拿Glide
          Glide glide = Glide.get(context.getApplicationContext());
          applicationManager =
              factory.build(
                  glide,
                  new ApplicationLifecycle(),//注意:这里是ApplicationLifecycle
                  new EmptyRequestManagerTreeNode(),
                  context.getApplicationContext());
        }
      }
    }

    return applicationManager;//返回RequestManager
  }

第6步,再看看传递Activity 的情况, 最终会调用FragmentGet 生成一个Fragment 来监听生命周期。这里是最重要的一个方法

java 复制代码
  public RequestManager get(@NonNull Activity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else if (activity instanceof FragmentActivity) {
      return get((FragmentActivity) activity);
    } else {
      assertNotDestroyed(activity);
      frameWaiter.registerSelf(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
      //注意:调用FragmentGet,这里会生成一个Fragment 用来监听生命周期
      return fragmentGet(activity, fm, /* parentHint= */ null, isActivityVisible(activity));
    }
  }

第7步 , fragmentGet 方法生成空白的Fragment,该Fragment 是用来管理请求的生命周期的,并且会和RequestManagerFactory工厂生成的RequestManager 绑定。

java 复制代码
  private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    //1. 通过getRequestManagerFragment生成一个空白的Fragment,用来管理请求的生命周期,核心方法!!
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
    RequestManager requestManager = current.getRequestManager();
    //2. 如果FragmentManager,为空,就用RequestManagerFactory工厂生成一个并且设给RequestManagerFragment
    if (requestManager == null) {
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      if (isParentVisible) {
        requestManager.onStart();
      }
      current.setRequestManager(requestManager);
    }
    //3. 返回RequestManager
    return requestManager;
  }

第8步 在看工厂如何生成FragmentManager 之前,先看看如何生成空白的Fragment------RequestManagerFragment,因为这个RequestManagerFragment最终要和RequestManager 绑定的。

java 复制代码
  private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint) {
    //1. 先缓存中取
    RequestManagerFragment current = pendingRequestManagerFragments.get(fm);
    //2.缓存里面没有,再通过 TAG 从FragmentManager 里拿
    if (current == null) {
      current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
      //3. 缓存没有,通过TAG 也拿不到,就初始化一个新的
      if (current == null) {
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        //4. 先放入缓存,以免下一次Glide请求会再生成一个空白的Fragment
        pendingRequestManagerFragments.put(fm, current);
        //5. 通过当前 Activity的 FragmentManager 开始提交添加一个 Fragment容器
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        //6. 这个空白的Fragment 添加到 FragmentManager 成功,通过 Handler 发送一个消息,清理缓存
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

上面的 getRequestManagerFragment 有一个很重要的点:采用了双重检测保证宿主、空白Fragment、RequestManager 一一对应

第一重保障:使用Map<android.app.FragmentManager, RequestManagerFragment>保存记录集合,解决多个请求只有一个空白Fragment

第二重保障:通过Handler 发送消息让空白的Fragment 马上添加到FragmentManager

FragmentManager 的事务本来就是通过Handler 发送消息来实现,通过Handler 发送消息有可能不会被马上执行,倘若空白的Fragment的消息一直在等待,那么下一次Glide请求就会再生成一个空白的Fragment。而通过Handler 发送删除消息,可以让空白的Fragment添加到FragmentManager马上执行并且清空缓存,这样下一次Glide 请求到来的时候,从FragmentManager的TAG 就能拿到Fragment, 不会再创建。

第9步,我们再回过头来看看怎样通过工厂RequestManagerFactory 来生成RequestManager的

java 复制代码
  private static final RequestManagerFactory DEFAULT_FACTORY =
      new RequestManagerFactory() {
        @NonNull
        @Override
        public RequestManager build(
            @NonNull Glide glide,
            @NonNull Lifecycle lifecycle,
            @NonNull RequestManagerTreeNode requestManagerTreeNode,
            @NonNull Context context) {
          //工厂里也是new 一个 RequestManager 
          return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
        }
      };

第10步,RequestManager 初始化,监听lifecycle的生命周期。而这个lifecycl就是空白Fragment里的ActivityFragmentLifecycle

java 复制代码
  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));
    glide.registerRequestManager(this);
    if (Util.isOnBackgroundThread()) {
      Util.postOnUiThread(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);//this 就是RequestManager 因此RequestManager就会监听Lifecycle生命周期
    }
    lifecycle.addListener(connectivityMonitor);

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

  //Requestmanager 已经监听了空白Fragment的lifecycle
  @Override
  public synchronized void onStart() {
    resumeRequests();//恢复请求
    targetTracker.onStart();
  }


  @Override
  public synchronized void onStop() {
    pauseRequests();//暂停请求
    targetTracker.onStop();
  }
java 复制代码
public class RequestManagerFragment extends Fragment {
  private static final String TAG = "RMFragment";
  private final ActivityFragmentLifecycle lifecycle;

  ......
    @Override
  public void onStart() {
    super.onStart();
    lifecycle.onStart();//转发生命周期
  }

  @Override
  public void onStop() {
    super.onStop();
    lifecycle.onStop();//转发生命周期
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    lifecycle.onDestroy();
    unregisterFragmentWithRoot();//转发生命周期
  }
}

到此,可以看到 RequestManager 通过监听空白Fragment 的 lifecycle 的生命周期来管理请求的生命周期的。

Glide.with 原理总结

Glide 初始化并且生成RequestManager,RequestManager 与 空白Fragment 的 lifecycle 生命周期绑定来管理后续的请求。

  1. 空白Fragment 持有ActivityFragmentLifecycle,当空白Fragment生命周期改变的时候,调用onStart()、onStop()、onDestroy()------>

2)ActivityFragmentLifecycle 持有LifecycleListener集合,其中RequestManager是其中的一个LifecycleListener,ActivityFragmentLifecycle遍历集合,调用LifecycleListener的onStart()、onStop()、onDestroy()------>

  1. RequestManager 实现了LifecycleListener, 在onStart()、onStop()、onDestroy()方法中进行请求的生命周期管理。
相关推荐
命运之手2 个月前
【Android】Glide模块工作原理
android·module·glide·工作原理·decoder
android1573 个月前
Android开发:Glide基本使用以及加载https图片(配合OkHttp实现)
android·okhttp·glide
bright7894 个月前
新版Glide检测生命周期原理
android·安卓·glide
一禅-小和尚4 个月前
LruCache、Glide和SmartRefreshLayout使用总结
glide
Sca_杰4 个月前
vue使用glide.js实现轮播图(可直接复制使用)
javascript·vue.js·glide
zhangphil5 个月前
Android Glide, first start based on loadThumbnail, Kotlin(二)
android·kotlin·glide
2401_856403035 个月前
AndroidX中Glide包冲突问题(1)
glide·androidx
大模型与计算机视觉5 个月前
扩散模型 GLIDE:35 亿参数的情况下优于 120 亿参数的 DALL-E 模型
人工智能·深度学习·大模型·glide·多模态·扩散模型·多模态大模型
zhangphil5 个月前
Android Glide, first start based on loadThumbnail, Kotlin(一)
android·kotlin·glide
starry陆离6 个月前
『项目整理』易CAR通项目说明文档-我的第一款APP
android·java·glide·项目经历