Glide 源码分析(一)

Glide源码分析

写在前面

一直在使用Glide进行图片的加载显示,想看看Glide的源码实现是如何做的,终于有时间阅读了下源码,写下来就当做个笔记,也分享给大家学习下。如果有错误,欢迎各位指正。

基本步骤

我们要加载并显示一张图片只需要一行代码,如下所示:

Glide.with(Context).load(source).into(target);

具体Glide中做了什么操作,怎么操作。我们进一步了解下。

源码下载

用添加依赖的方式将Glide引入到项目中的,在Android Studio中就可以直接进行查看。
也可以在GitHub将源码下载下来,分析用的源码是4.8.0,下载点这里:https://github.com/bumptech/glide/releases/tag/v4.8.0

源码分析

按照加载步骤,就是三步:先with(),再load(),最后into()。那么我们开始一步步阅读源码,先从with()看起。

  public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }
  
  public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
  }
  
  public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
  }
  
  public static RequestManager with(@NonNull Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
  }
  
  public static RequestManager with(@NonNull android.app.Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
  }
  
  public static RequestManager with(@NonNull View view) {
    return getRetriever(view.getContext()).get(view);
  }

with() 是一组重载的静态方法,每个with()方法传入的参数不同,有fragment、activity、context三种参数。
with() 返回的是RequestManager,所以应该可以猜到,接下来的load()的操作肯定是在RequestManager 中进行。
with() 内部调用了getRetriever(),紧接着又调用了get方法。一般,单例模式都是用get方法返回唯一实例的,所以可以想到是在get中返回了RequestManager对象 。
那getRetriever()中的逻辑是什么?又做了什么操作?

  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    ...
    return Glide.get(context).getRequestManagerRetriever();
  }

在getRetriever方法内部调用Glide的get方法返回单例对象,再调用Glide的getRequestManagerRetriever方法,返回RequestManagerRetriever。我们进Glide的get中看具体做了什么操作。

/**
  public static Glide get(@NonNull Context context) {
    if (glide == null) {
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context);
        }
      }
    }
    return glide;
  }

在get方法内部采用双重锁检测机制(DCL,单例模式的实现方法之一)检查并初始化Glide后返回glide唯一实例,glide变量在声明的时候用是volatile关键字修饰。可知上一步中getRequestManagerRetriever是在Glide中获取RequestManagerRetriever。重点来了,看看如何进行检查和初始化Glide的。

private static void checkAndInitializeGlide(@NonNull Context context) {
    // In the thread running initGlide(), one or more classes may call Glide.get(context).
    // Without this check, those calls could trigger infinite recursion.
    if (isInitializing) {
      throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
          + " use the provided Glide instance instead");
    }
    isInitializing = true;
    initializeGlide(context);
    isInitializing = false;
  }

在方法内调用initializeGlide(context),在initializeGlide(context)中又调用了initializeGlide(context, new GlideBuilder())。

  @SuppressWarnings("deprecation")
  private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
    Context applicationContext = context.getApplicationContext();
    GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
    List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
      manifestModules = new ManifestParser(applicationContext).parse();
    }
	...
	移除相同的GlideModule
	...
    RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory() : null;
    ...
    设置Glide Builder
    ...
    Glide glide = builder.build(applicationContext);
    ...
    //注册组件
    ...
    //注册内存优化的系统回调
    applicationContext.registerComponentCallbacks(glide);
    Glide.glide = glide;
  }

到目前为止,glide的初始化已完成,并创建了glide唯一实例。
然后返回到上面的getRequestManagerRetriever,继续跟踪。

  @NonNull
  public RequestManagerRetriever getRequestManagerRetriever() {
    return requestManagerRetriever;
  }

拿到Glide的成员变量requestManagerRetriever,继续返回上一步,跟踪它的get方法

@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)) {
      if (context instanceof FragmentActivity) {
        return get((FragmentActivity) context);
      } else if (context instanceof Activity) {
        return get((Activity) context);
      } else if (context instanceof ContextWrapper) {
        return get(((ContextWrapper) context).getBaseContext());
      }
    }

    return getApplicationManager(context);
  }

在这里,我们可以看到with传进来的参数派上用场了,根据context的类型走不同的分支。
如果context是null,则直接抛出异常。如果不是在主线程或者传进来的context是Application类型则返回getApplicationManager,Application对象的生命周期就是应用的生命周期,这种情况下它和应用的生命周期是同步的,在应用关闭退出的时候,Glide的加载也会自动终止。如果不是上面的情况则根据context的类型执行对应的执行get()方法。


  @NonNull
  public RequestManager get(@NonNull FragmentActivity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      FragmentManager fm = activity.getSupportFragmentManager();
      return supportFragmentGet(
          activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

  @NonNull
  public RequestManager get(@NonNull Fragment fragment) {
    Preconditions.checkNotNull(fragment.getActivity(),
          "You cannot start a load on a fragment before it is attached or after it is destroyed");
    if (Util.isOnBackgroundThread()) {
      return get(fragment.getActivity().getApplicationContext());
    } else {
      FragmentManager fm = fragment.getChildFragmentManager();
      return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
    }
  }

可以看到,如果是在后台线程中,则按Application类型处理。不管传进来是Activity还是fragment,在get方法中最终都调用了supportFragmentGet方法,

@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;
  }

重点来了,在supportFragmentGet方法中创建了一个没有界面的fragment,它的生命周期和context保持一致,这样context在销毁的时候,fragment可以检测到这个销毁操作,那么Glide的加载在fragment销毁的时候也会同步停止。最终返回了requestManager实例。至此with的流程走完了,与咱们开头看到的with方法返回RequestManager类型的结果是一致的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值