ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Glide源码分析——Request管理

2021-12-05 17:58:47  阅读:163  来源: 互联网

标签:SupportRequestManagerFragment Glide get Fragment Request RequestManager 对象 源码


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种情况:

  • Activity
  • FragmentActivity
  • Fragment
  • android.app.Fragment
  • Application Context

除了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;
}

这个过程可总结为:

  • 判断当前FragmentActivity上是否已经添加了Tag为FRAGMENT_TAG的Fragment
  • 如果没有,则创建一个没有界面的SupportRequestManagerFragment对象,并将它add到当前FragmentActivity;然后创建RequestManager对象,并将该对象引用传给SupportRequestManagerFragment对象。 SupportRequestManagerFragment的构造方法中会创建ActivityFragmentLifecycle对象,SupportRequestManagerFragment生命周期发生变化时会调用ActivityFragmentLifecycle中对应生命周期方法。RequestManager实现了LifecycleListener接口,当创建RequestManager对象时会向SupportRequestManagerFragment中的ActivityFragmentLifecycle注册LifecycleListener,所以当ActivityFragmentLifecycle中的生命周期方法发生变化时,RequestManager就能感知到。

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

RequestManager对Request管理

类关系

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

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

  • RequestManagerRetriever根据get()方法中的参数返回RequestManager对象;

  • RequestManager实现了LifestyleListener接口,并持有Lifecycle和ReqeustTracker对象的引用;

  • Lifecycle接口有两个实现类:ApplicationLifecycle和ActivityFragmentLifecycle,两者的区别是前者只在addListener()就会回调LifecycleListener.onStart()方法,而且也没有调用onStop和onDestroy()方法的地方。这就是说如果你在Fragment/Activity中点用Glide.with()传入的是Application Context时,这个请求不受Fragment/Activity生命周期的影响,会得到执行;但是不建议这么做,因为当界面消失后继续加载也没有意义。

  • SupportRequestManagerFragment持有RequestManager和ActivityFragmentLifecycle对象的引用;

  • 每个加载图片的请求会被封装成一个Reqeust对象;Request由ReqeustTracker管理,而ReqeustTracker对Request的管理是由RequestManager驱动的。

  • RequestManager对Reqeust间接地管理又是受SupportRequestManagerFragment的生命周期影响,所以最终SupportRequestManagerFragment的生命周期作用着图片加载请求。

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的管理整体流程很简单,主要分为以下几个步骤:

  • SupportRequestManagerFragment对象创建时会创建ActivityFragmentLifecycle对象;RequestManager对象创建时会向SupportRequestManagerFragment中的ActivityFragmentLifecycle注册LifecycleListener回调。
  • 当SupportRequestManagerFragment生命周期发生变化时(onStart、onStop、onDestroy)调用ActivityFragmentLifecycle中对应的生命周期方法,在这些方法中会调用LifecycleListener中的方法,从而RequestManager就能根据SupportRequestManagerFragment的生命周期对Request进行管理。

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

  • RequestManager是用来管理图片加载请求(Request);
  • RequestManager对象的创建依赖与Glide.with()调用的线程和传入的参数。对于在非UI线程下调用和参数为Application Context情况下,则先判断是否已创建Application Context对应的RequestManager对象,没有则创建,有则返回该对象引用。对于参数为FragmentActivity和Fragment(指support或者androidx包中的Fragment),会判断它是否包含无界面的SupportRequestManagerFragment,如果有则通过SupportRequestManagerFragment.getRequestManager()返回RequestManager对象引用;如果没有则先创建SupportRequestManagerFragment对象,并将它add到FragmentActivity/Fragment中,然后创建RequestManager对象,并向SupportRequestManagerFragment中的ActivityFragmentLifecycle注册LifecycleListener,最后返回创建的对象引用。对于参数为Activity和android.app.Frament,原理和FragmentActivity/Fragment一样,只是创建的Fragment对象是RequestManagerFragment。
  • 当FragmentActivity/Fragment(Activity/android.app.Fragment)生命周期发生变化时,其界面上的SupportRequestManagerFragment生命周期也会发生变化,当SupportRequestManagerFragment发生变化时,会通过ActivityFragmentLifecycle通知LifecycleListener接口实现者RequestManager,RequestManager根据SupportRequestManagerFragment的生命周期变化对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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有