编程语言
首页 > 编程语言> > Glide源码分析——Request管理

Glide源码分析——Request管理

作者:互联网

Glide作为一个优秀的图片加载框架,有很多值得我们学习的地方,这次我们来看看它是如何管理图片加载的请求吧;特别是它是如何感知Activity/Fragment的生命周期的方式。

文章目录


 在Glide中会把每个图片加载请求封装成一个Request对象,而这些Request对象的管理里是RequestManager。在了解Request Manager对Request管理之前,我们先来看下Glide请求显示过程,请求过程大致如下时序图所示:
load_overview
 时序图中省略了RequestManager对象创建、Request具体加载过程等细节;关于Request具体加载过程,我们以后的文章再讲解,我们这篇文章主要看下RequestManager对象创建、它是如何感知Activity/Fragment生命周期以及它对Request的管理。

RequestManager对象创建

 RequestManager,从名称也能看出它是管理Request的对象,事实上也确实如此。RequestManager对象创建是在RequestManagerRetriever.get()方法过程中实现的, RequestManagerRetriver有多个重载的get()方法,这跟调用Glide.with()时传入的参数有关。

public RequestManager get(@NonNull Activity activity){...}
public RequestManager get(@NonNull FragmentActivity activity){...}
public RequestManager get(@NonNull Context context){...}
public RequestManager get(@NonNull Fragment fragment){...}
public RequestManager get(@NonNull android.app.Fragment fragment){...}
public RequestManager get(@NonNull View view){...}

虽重载方法有6个,但实际上创建RequestManager对象只有5种情况:

除了ApplicationContext,其他几种情况都会创建一个SupportRequestManagerFragment(备注:Activity和android.app.Fragment情况会创建RequestManagerFragment,后面的分析都是基于SupportRequestManagerFragment,他们的原理是一致的)与创建的RequestManager对象关联;RequestManager对Request的管理会受SupportRequestManagerFragment生命周期的影响。接下来我们看下RequestManager对象创建过程,先看RequestManagerRetriever.get(FragmentActivity activity)方法

//RequestManagerRetriever.java
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
  if (Util.isOnBackgroundThread()) {
    //如果是非UI线程,则调用get(Context context)方法,并传入Application Context
    return get(activity.getApplicationContext());
  } else {
    assertNotDestroyed(activity);
    frameWaiter.registerSelf(activity);
    //注意这个地方,调用的是getSupportFragmentManager()方法;
    FragmentManager fm = activity.getSupportFragmentManager();
    return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
  }
}

Application Context实现

我们先看非UI线程下创建RequestManager对象,在此条件下会调用get(Context context)方法,并传入Application Context。在get(Context context)方法实现种,如果是非UI线程会调用getApplicationManager(Context context)方法,并返回RequestManager对象,我们直接看getApplicationManager(Context context)方法。

//RequestManagerRetriever.java
@NonNull
private RequestManager getApplicationManager(@NonNull Context context) {
  //通过double-check的方式创建applicationManager对象
  if (applicationManager == null) {
    synchronized (this) {
      if (applicationManager == null) {
        Glide glide = Glide.get(context.getApplicationContext());
        applicationManager =
            //通过factory创建RequestManager对象
            factory.build(
                glide,
                new ApplicationLifecycle(),//注意这里创建的是ApplicationLifecycle()对象
                new EmptyRequestManagerTreeNode(),
                context.getApplicationContext());
      }
    }
  }

  return applicationManager;
}

applicationManager是RequestManagerRetriever对象变量,通过double-check的方式保证了applicationManager对象的唯一性。这里需要注意的一点是创建RequestManager的时候传入的Lifecycle参数是ApplicationLifecycle对象引用,至于为什么要注意,我们后面再讲。

FragmentActivity实现

 接下来,看下get(FragmentActivity activity)方法UI在线程下的实现

//RequestManagerRetriever.java
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
  if (Util.isOnBackgroundThread()) {
    //如果是非UI线程,则调用get(Context context)方法,并传入Application Context
    return get(activity.getApplicationContext());
  } else {
    assertNotDestroyed(activity);
    frameWaiter.registerSelf(activity);
    //注意这个地方,调用的是getSupportFragmentManager()方法;
    //在get(Fragment fragment)方法实现中,fm = fragment.getChildFragmentManager();
    FragmentManager fm = activity.getSupportFragmentManager();
    return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
  }
}

@NonNull
private RequestManager supportFragmentGet(
    @NonNull Context context,
    @NonNull FragmentManager fm,
    @Nullable Fragment parentHint,
    boolean isParentVisible) {
  SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
  RequestManager requestManager = current.getRequestManager();
  if (requestManager == null) {
    Glide glide = Glide.get(context);
    //创建RequestManager并将SupportRequestManagerFragment中的Lifecycle对象引用作为参数传入
    requestManager =
        factory.build(
            glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
    if (isParentVisible) {
      requestManager.onStart();
    }
    //给SupportRequestManagerFragment设置RequestManager,这样RequestManager
    //和SupportRequestManagerFragment就关联起来了。
    current.setRequestManager(requestManager);
  }
  return requestManager;
}

@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
    @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
  SupportRequestManagerFragment current =
      //判断是否已经添加过Tag为FRAGMENT_TAG的Fragment
      (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
  if (current == null) {
    current = pendingSupportRequestManagerFragments.get(fm);
    if (current == null) {
      //创建SupportRequestManagerFragment对象,SupportRequestManagerFragment是没有界面的Fragment
      current = new SupportRequestManagerFragment();
      current.setParentFragmentHint(parentHint);
      pendingSupportRequestManagerFragments.put(fm, current);
      //调用add()方法时也没有传一个layout id,所以这个Fragment对用户是完全不可见的
      fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
      handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
    }
  }
  return current;
}

这个过程可总结为:

对于RequestManagerRetriever的其他get()方法,逻辑基本一样,这里就不展开。接下来我们看下RequestManager对Request的管理方式。

RequestManager对Request管理

类关系

在看RequestManager对Request管理之前,我们先来了解下与RequestManager相关的类图
在这里插入图片描述

RequestManager相关的类图如上,稍微解释下他们直接的关系。

RequestManager和Fragment/Activity的关系

在对RequestManager关系类图有一定了解后,我们再看下RequestManager、Fragment/Activity和SupportRequestManagerFragment之间的关系。细心的同学在看RequestManager对象创建应该能略知一二,他们的关系如下图所示:
在这里插入图片描述

当我们在Activity/Fragment中调用Glide.with().load(url).into(imageView)并传入Activity/Fragment对象引用作为with参数时,会在对应的Activity/Fragment创建一个SupportRequestManagerFragment并add到Activity/Fragment。注意,这里说的Glide.with()参数是指当前Activity/Fragment对象的引用。从图中能明显看出Activity/Fragment、SupportRequestManagerFragment和RequestManager之间的关系。我们以上面图对应的代码为例,MyActivity中通过Glide加载图片并显示(with()方法传入的为MyActivity对象引用);在MyActivity中add一个MainFragment,MainFramgent中又add一个SubFragment,在两个Fragment中都通过Glide加载图片并显示且with()传入的都是他们对应的引用。

关于他们之间的关系我们可以通过MAT工具来验证

首先dump出堆内存文件,并通过hprof-convert转换成MAT工具能识别的文件(关于dump堆内存文件和MAT工具使用可参考《Android 应用内存泄漏分析(实战篇)》)。通过MAT工具打开,在Histogram界面过滤SupportRequestManagerFragment,可以看到该类有三个实例对象,和上面的关系图对应上了。
在这里插入图片描述
接着通过选中对象,然后右键List objects > with outgoing reference 查看三个SupportRequestManagerFragment实例持有了哪些对象的引用
在这里插入图片描述
在这里插入图片描述
从上面的第二张图可以看出,每个SupportRequestManagerFragment对象持有一个不同FrequestManager对象的引用,并且SupportRequestManagerFragment@0x13c0f6a0、SupportRequestManagerFragment @ 0x13c0e540的mParentFragment分别指向MainFragment和SubFramgent对象;至于SupportRequestManagerFragment @ 0x13c0e698,它是MyActivity中的SupportRequestManagerFragment 对象,它的mParentFragment则为null,这一点可以从下图得到验证
在这里插入图片描述

在有前面的基本认知后,现在再来看下RequestManager是如何管理Request

RequestManager如何管理Request

在这里插入图片描述

RequestManager对Request的管理整体流程很简单,主要分为以下几个步骤:

到此,我们已经知道RequestManager的创建以及对Request的管理方式,最后稍稍总结下:

能学到什么

感知Activity/Fragment的生命周期的方法

 对Request的管理需要定义个RequestManager类,这有一定工作经验的同学都能想到。在这里更值得学习的是感知Activity/Fragment都生命周期的方法,Glide就使用了一个很巧妙的方法来感知Activity/Fragment的生命周期,它通过在Activity/Fragment中添加一个无界面的Fragment(SupportRequestManagerFragment或者RequestManagerFragment),RequestManager根据这个Fragment的生命周期变化由来管理Request请求。在早期的Jetpack(当时叫法还是“Android架构组件”) ViewModel也是跟一个没有界面的HolderFragment绑定,从推出的时间来看,Jetpack可能借鉴了Glide;不过最新的Jetpack中已经抛弃了创建一个无界面的做法了,因为后面把Fragment、ViewModel、Lifecycle等整合到androidx包之后,就可以直接修改Fragment了。不过对于我们开发者而言,这种感知Activity/Fragment生命周期的方法还是值得借鉴的,特别是当你做自己的框架而又不想依赖第三方库的时候。

标签:SupportRequestManagerFragment,Glide,get,Fragment,Request,RequestManager,对象,源码
来源: https://blog.csdn.net/sd_zhuzhipeng/article/details/121732376