不敢说懂你 - Glide硬核源码剖析

本文详细剖析了Glide的加载流程,包括with()、load()、into()方法的实现,探讨了缓存加载、线程切换的原理,并介绍了Glide如何感知Activity。通过源码分析,揭示了Glide如何从内存、磁盘或网络加载图片,并在主线程中设置图片。
摘要由CSDN通过智能技术生成

问题

Glide加载流程?

Glide整体架构?

Glide数据加载的来源?

Glide缓存加载的流程?

Glide线程切换原理?

Glide如何感知Activity?

Glide哪种情况会返回应用级的RequestManager?

带着一些问题去阅读…

使用示例

本篇主要基于glide:4.12.0进行分析。下面是Glide主要的使用示例。

repositories {
  google()
  mavenCentral()
}

dependencies {
  implementation 'com.github.bumptech.glide:glide:4.12.0'
  annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
}

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

可以看到,Glide的加载主要分三步:with()load()into()。理解了这三步Glide做了什么,基本就理解了Glide源码加载图片的大体逻辑和框架了。

with()

Glide的with()方法的目的是根据不同的上下文context获得RequestManager对象。

RequestManager对象解释:A class for managing and starting requests for Glide.

下面开始详细分析。

首先看Glide中with()方法所有的重载函数:

RequestManager with(Context context)
RequestManager with(android.app.Activity)
RequestManager with(androidx.fragment.app.Fragment)
RequestManager with(androidx.fragment.app.FragmentActivity)
RequestManager with(View view)

以Glide中的 with(android.app.Activity)为例:

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

可以看到,RequestManagergetRetriever(activity).get(activity)得到,因此有两个问题:

1 getRetriever(activity)获得什么对象?

2 这个对象的get()获得什么?

首先看第一个问题,看getRetriever(activity):

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

getRetriever(activity)获得了RequestManagerRetriever对象。

接下来进RequestManagerRetriever对象看它的get()实现,它根据with()重载方法参数的不同进行不同重载:

RequestManager get(Context context)
RequestManager get(android.app.Activity)
RequestManager get(androidx.fragment.app.Fragment)
RequestManager get(androidx.fragment.app.FragmentActivity)
RequestManager get(View view)

以其中一个为例:

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

可以看到,RequestManager返回两种类型,分别是当是子线程时的get(activity.getApplicationContext());和其他的supportFragmentGet()

首先看with()在子线程中统一返回的应用级别RequestManager单例,看 get(activity.getApplicationContext());

 @NonNull
  public RequestManager get(@NonNull Context context) {
   
    ...
       if (context instanceof FragmentActivity) {
   
        return get((FragmentActivity) context);
    ...
  }

继续追这个get()方法的具体实现:

  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
          && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
   
        return get(((ContextWrapper) context).getBaseContext());
      }
    }
    return getApplicationManager(context);
  }

看到这一行:if (Util.isOnMainThread() && !(context instanceof Application)),这行判断不仅决定了子线程中直接返回getApplicationManager(context)方法,而且当这个传入的context是Application时,也返回全局的getApplicationManager(context)方法获得的应用级别RequestManager

继续追这个getApplicationManager(context)方法的具体实现:

 @NonNull
  private RequestManager getApplicationManager(@NonNull Context context) {
   
    if (applicationManager == null) {
   
      synchronized (this) {
   
        if (applicationManager == null) {
   
          Glide glide = Glide.get(context.getApplicationContext());
          applicationManager =factory.build(...);
        }
      }
    }
    return applicationManager;
  }

至此我们知道了with()返回是应用级别RequestManager单例:applicationManager的两种情况:子线程+context=Application

那么不是子线程时的supportFragmentGet()呢,这种情况又是如何生成的RequestManager?我们具体看下RequestManagerRetriever.supportFragmentGet()

 private RequestManager supportFragmentGet(@NonNull Context context,@NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
   
   
    //获取空fragment,无则创建
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
    
   // 让fragment持有RequestManager
   RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
   
      //如果空fragment没有RequestManager,就创建一个
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      ...
      //让空fragment持有RequestManager
      current.setRequestManager(requestManager);
    }
   
   //返回页面级别的RequestManager
    return requestManager;
  }

继续看这个新fragment怎么创建的:

private SupportRequestManagerFragment getSupportRequestManagerFragment(
    @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
   
   //通过tag找到Activity中的空fragment
  SupportRequestManagerFragment current =
      (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
  if (current == null) {
   
     //findFragmentByTag没找到空fragment,有可能是延迟问题?再从Map中找一下
    current = pendingSupportRequestManagerFragments.get(fm);
    if (current == null) {
   
       //确实没有空fragment,就创建一个
      current = new SupportRequestManagerFragment();
      current.setParentFragmentHint(parentHint);
      //缓存进Map
      pendingSupportRequestManagerFragments.put(fm, current);
      //空fragment添加到Activity,使其能感知Activity的生命周期
      fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
      handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
    }
  }
  return current;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许进进

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值