Glide根本用法及With方法源码剖析

打印 上一主题 下一主题

主题 1310|帖子 1310|积分 3930

引入

   Glide是一个快速高效的Android图片加载库
  专门用来资助开辟者从网络、文件体系或应用资源中加载图片,并显示在 ImageView 或其他 UI 组件上。它具备高效的缓存机制和解码本领,能够处理惩罚图片、GIF、视频缩略图等多种媒体文件。
  优点


  • 高效的图片加载和缓存:Glide 会自动处理惩罚图片的内存和硬盘缓存,镌汰内存消耗,优化性能。
  • GIF 和视频帧加载支持:除了常规图片,Glide 还能加载 GIF 动画和视频缩略图,这让它在处理惩罚多媒体内容时非常灵活。
  • 动态调整图片大小:Glide 可以根据 ImageView 的大小自动调整图片尺寸,避免加载过大或过小的图片,从而镌汰内存占用。
  • 高度可配置:Glide 提供了丰富的 API,允许开辟者自界说加载行为,比如设置占位符、错误图标、图片变换等。
  • 与 RecyclerView、ListView 集成良好:Glide 可以高效地加载和显示大批量图片,特别是在利用 RecyclerView 或 ListView 时,滑动时的图片加载更加顺畅。
  • 后台线程自动处理惩罚:Glide 会自动将图片加载任务放在后台线程中执行,避免在主线程中举行 I/O 操作,提拔应用相应速率。
  • 灵活的网络栈集成:Glide 默认利用的是基于 HttpUrlConnection 的网络请求栈,但它的设计允许开辟者轻松替换成其他网络库,比如 Google 的 Volley 或 Square 的 OkHttp。
利用步调

导入依靠

  1.     implementation 'com.github.bumptech.glide:glide:4.11.0'
  2.     annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
复制代码
权限

  1. <!--    如果需要从 URL 或一个网络连接中加载数据-->
  2.     <uses-permission android:name="android.permission.INTERNET" />
  3. <!--    如果需要从本地文件夹或 DCIM 或图库中加载图片-->
  4.     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
复制代码
利用

   

  • 利用 Glide 加载本地图片并将其显示到 ImageView 中
  1. public class MainActivity extends AppCompatActivity {
  2.     @Override
  3.     protected void onCreate(Bundle savedInstanceState) {
  4.         super.onCreate(savedInstanceState);
  5.         setContentView(R.layout.activity_main);
  6.         ImageView image = findViewById(R.id.imageView);
  7.         Glide.with(this)
  8.                 .load(R.drawable.a)
  9.                 .into(image);
  10.     }
  11. }
复制代码
  

  • 加载网络图片
  1. Glide.with(this).load("https://i0.hdslb.com/bfs/archive/d04368506b906a0d4ac62217e93467cdaa29af90.jpg").into(image);
复制代码
  

  • 加载本地文件
  1. File file = new File("/storage/emulated/0/Download/example.jpg");
  2. Glide.with(this).load(file).into(image);
复制代码


  • Glide.with(this)

    • 这是 Glide 的入口,用于获取一个 RequestManager 实例,它负责后续的图片加载请求。
    • 参数 this 通常是当前的 Activity 或 Fragment,表现 Glide 的生命周期将与该 Activity 或 Fragment 绑定。这样可以确保在 Activity 或 Fragment 销毁时,Glide 也会自动取消图片请求,避免内存走漏。

  • load(R.drawable.dp)

    • 这里的 load() 方法用来指定要加载的图片资源,获取到一个RequestManager实例,通过 RequestManager,Glide 可以自动管理图片的内存缓存和磁盘缓存,避免重复加载和浪费资源。RequestManager 提供了各种链式调用方法来配置加载选项,比如占位符、错误图片、缩放类型等。
    • 该方法也可以接收其他类型的参数,比如图片的 URL、文件路径、Bitmap 对象等。

  • into(image)

    • into() 方法指定目标 ImageView,即将图片加载到哪个控件上。

其他用法



  • 占位符:设置图片加载前的占位图片。
  • 错误图片:设置图片加载失败时显示的图片。
  • 裁剪模式:指定图片怎样适应 ImageView 的大小(例如:居中裁剪、适应宽高等)。
  • 缓存策略:指定图片的内存缓存和磁盘缓存策略。
  • 圆角/圆形图片:对图片举行圆角处理惩罚或转换为圆形。
占位符

   占位符是当请求正在执行时被展示的 Drawable 。
  当请求乐成完成时,占位符会被请求到的资源替换。
  如果被请求的资源是从内存中加载出来的,那么占位符大概根本不会被显示。
  如果请求失败而且没有设置 error Drawable ,则占位符将被连续展示。
  如果请求的url/model为 null ,而且 error Drawable 和 fallback 都没有设置,那么占位符也会继续显示。
  错误图片

   error Drawable 在请求永久性失败时展示。
  error Drawable 在请求的url/model为 null ,且并没有设置 fallback Drawable 时展示。
  1. Glide.with(this)
  2.         .load("https://i1.hdslb.com/bfs/archive/bea5b65f3328a6027ca6ab173c3e3ccaa98f5d21.jpg")
  3.         .placeholder(R.drawable.img_loading) // 占位图
  4.         .error(R.drawable.img_error) // 错误显示图片
  5.         .into(image);
复制代码


  • 占位符是在主线程从Android Resources加载的
后备回调符

fallback Drawable 在请求的url/model为 null 时展示。目标是允许用户指示 null 是否为可接受的正常情况。
例如,一个用户的个人资料 URL 为 null,这大概意味着用户没有设置头像。在这种情况下,应该利用默认头像。
默认情况下Glide将 null 作为错误处理惩罚,所以可以接受 null 的应用应当显式地设置一个 fallback Drawable 。
  1. Glide.with(fragment)
  2.   .load(url)
  3.   .fallback(R.drawable.fallback)
  4.   .into(view);
复制代码
圆角

  1. Glide.with(this)
  2.                 .load("https://i0.hdslb.com/bfs/archive/d04368506b906a0d4ac62217e93467cdaa29af90.jpg")
  3.                 .placeholder(R.drawable.img_loading)
  4.                 .error(R.drawable.img_error)
  5.                 .transform(new CircleCrop())// 裁剪为圆形
  6.                 .into(image);
复制代码
  1. Glide.with(this)
  2.                 .load("https://i0.hdslb.com/bfs/archive/d04368506b906a0d4ac62217e93467cdaa29af90.jpg")
  3.                 .placeholder(R.drawable.img_loading)
  4.                 .error(R.drawable.img_error)
  5.                 .transform(new RoundedCorners(200)) //圆角
  6.                 .into(image);
复制代码
过渡动画

TransitionOptions用于决定你的加载完成时会发生什么
可以应用以下变换:


  • View淡入
  • 与占位符交叉淡入
  • 或者什么都不发生
与占位符交叉淡入结果:
  1. Glide.with(context)
  2.      .load(imageUrl)
  3.      .transition(DrawableTransitionOptions.withCrossFade()) // 使用淡入淡出效果
  4.      .into(imageView);
复制代码
自界说过渡动画:
如果必要自界说过渡动画,可以利用 TransitionOptions 类和 Glide 的 RequestOptions 结合利用。可以通过 TransitionDrawable 或其他动画结果举行实现。
  1. Glide.with(context)
  2.      .load(imageUrl)
  3.      .transition(GenericTransitionOptions.with(R.anim.zoom_in)) // 使用自定义动画
  4.      .into(imageView);
复制代码
大小调整


  • override()
override(width, height) 方法可以让你明白指定加载图片的宽度和高度,强制 Glide 调整图片大小。
  1. Glide.with(context)
  2.      .load(imageUrl)
  3.      .override(300, 200) // 将图片调整为 300x200 像素
  4.      .into(imageView);
复制代码

  • fitCenter()
fitCenter() 方法会将图片等比例缩放到 ImageView 中,确保整个图片都能显示出来,而不裁剪图片。
  1. Glide.with(context)
  2.      .load(imageUrl)
  3.      .fitCenter() // 等比例缩放,确保整个图片适应 ImageView
  4.      .into(imageView);
复制代码

  • centerCrop()
centerCrop() 方法会将图片等比例缩放并裁剪,确保填满整个 ImageView。如果图片的比例与 ImageView 不符,图片的边缘会被裁剪掉。
  1. Glide.with(context)
  2.      .load(imageUrl)
  3.      .centerCrop() // 裁剪并填充 ImageView
  4.      .into(imageView);
复制代码

  • scale()
如果必要手动控制缩放因子,可以利用 scale() 方法来实现。这个方法允许你通过传入缩放因子来调整图片。
  1. Glide.with(context)
  2.      .load(imageUrl)
  3.      .scale(0.5f) // 将图片缩放至原始大小的 50%
  4.      .into(imageView);
复制代码
gif



  • 加载 GIF
如果你想强制将 GIF 作为动画加载,可以利用 asGif() 方法:
  1. Glide.with(this)
  2.     .load("https://pa1.narvii.com/7938/29d490319494e7cc1b4713464a64ce8b35a22099r1-498-446_hq.gif")
  3.     .into(image);
复制代码


  • 将 GIF 看成 Bitmap 显示
  1. Glide.with(this)
  2.     .asBitmap()
  3.     .load(gifUrl)
  4.     .into(image);
复制代码


  • 显示本地视频缩略图
要从本地视频文件中加载缩略图,你可以利用以下代码:
  1. String filePath = "/storage/emulated/0/Pictures/targetVideo.mp4";
  2. GlideApp  
  3.     .with(context)
  4.     .asBitmap()  // 加载为 Bitmap
  5.     .load(Uri.fromFile(new File(filePath)))  // 指向本地视频文件的 URI
  6.     .into(imageViewGifAsBitmap);  // 目标 ImageView
复制代码
缩略图

在加载主图像时同时加载其低分辨率的缩略图。提拔用户体验,镌汰用户等候加载主图像时看到空缺或加载指示器的时间。


  • thumbnail() 允许你为主请求指定一个缩略图请求,这样在主图像加载期间会先展示缩略图,提拔用户体验

  • 加载长途图像和缩略图
  1. Glide.with(fragment)
  2.   .load(url)  // 主图像的 URL
  3.   .thumbnail(Glide.with(fragment)
  4.     .load(thumbnailUrl))  // 缩略图的 URL
  5.   .into(imageView);
复制代码


  • 注意:确保 thumbnailUrl 指向的图片分辨率低于主 URL 指向的图片。

  • 加载本地图像和缩略图
  1. int thumbnailSize = 100; // 指定缩略图的大小
  2. Glide.with(fragment)
  3.   .load(localUri)  // 主图像的本地 URI
  4.   .thumbnail(Glide.with(fragment)
  5.     .load(localUri)  // 再次加载相同的本地图像
  6.     .override(thumbnailSize))  // 强制设置缩略图的尺寸
  7.   .into(imageView);
复制代码
利用RequestOptions



  • 想让你的应用的不同部分之间共享雷同的加载选项,你也可以初始化一个新的 RequestOptions 对象,并在每次加载时通过 apply() 方法传入这个对象:
   RequestOptions 是一个类,用来配置图片加载请求的各种选项。通过它可以更加灵活地定制图片加载过程,包罗设置占位符、错误图片、图片缩放方式、裁剪模式、缓存策略等。
  1. RequestOptions requestOptions = new RequestOptions()
  2.         .placeholder(R.drawable.img_loading) // 占位图
  3.         .error(R.drawable.img_error) // 错误显示图片
  4. ImageView image = findViewById(R.id.imageView);
  5. Glide.with(this)
  6.         .load("https://i1.hdslb.com/bfs/archive/bea5b65f3328a6027ca6ab173c3e3ccaa98f5d21.jpg")
  7.         .apply(requestOptions)
  8.         .into(image);
复制代码
  apply()方法可以被调用多次,因此 RequestOption 可以被组合利用。如果 RequestOptions 对象之间存在相互冲突的设置,那么只有最后一个被应用的 RequestOptions 会见效。
  缓存机制

Glide 的缓存主要分为两个层次:

  • 内存缓存

    • 内存缓存用于快速加载已经加载过的图像,避免重复下载。这可以明显进步图像的显示速率。
    • 默认情况下,Glide 会在内存中缓存加载的图像

  • 磁盘缓存

    • 磁盘缓存用于存储较大的图像资源,Glide 会将图像下载到设备的存储中。
    • 磁盘缓存的长处是即使在应用重启或用户下次打开应用时,已经缓存的图像仍然可用,镌汰了不必要的网络请求。

默认会利用内存和硬盘缓存
设置缓存策略

你可以利用 Glide 提供的缓存策略来控制缓存行为:


  • 跳过内存缓存
    禁用内存缓存,利用 skipMemoryCache(true):
    1. Glide.with(context)
    2.     .load(imageUrl)
    3.     .skipMemoryCache(true)  // 跳过内存缓存
    4.     .into(imageView);
    复制代码
  • 自界说磁盘缓存策略
    1. Glide.with(context)
    2.     .load(imageUrl)
    3.     .diskCacheStrategy(DiskCacheStrategy.ALL)  // 缓存所有版本的图像
    4.     .into(imageView);
    复制代码
   磁盘缓存策略选项
  

  • DiskCacheStrategy.NONE:不利用磁盘缓存
  • DiskCacheStrategy.SOURCE:只缓存原始数据(未转换的图像)
  • DiskCacheStrategy.RESULT:只缓存转换后的结果(例如,缩略图)
  • DiskCacheStrategy.ALL:缓存所有版本的图像(原始数据和转换后的结果)
  • DiskCacheStrategy.AUTOMATIC (长途数据:存储原始数据;本地数据:存储变换过的缩略图)
  清理缓存

如果必要清理 Glide 的缓存,可以在适当的地方调用如下方法:


  • 清理内存缓存
    1. Glide.get(context).clearMemory();
    复制代码
  • 清理磁盘缓存
    1. new Thread(new Runnable() {
    2.     @Override
    3.     public void run() {
    4.         Glide.get(context).clearDiskCache();
    5.     }
    6. }).start();
    复制代码
利用集成库

OkHttp

添加一个对 OkHttp 集成库的依靠:
  1. compile "com.github.bumptech.glide:okhttp3-integration:4.11.0"
复制代码
添加 OkHttp 集成库的 Gradle 依靠将使 Glide 自动开始利用 OkHttp 来加载所有来自 http 和 https URL 的图片。
Volley

  1. compile "com.github.bumptech.glide:volley-integration:4.11.0"
复制代码
添加 Volley 集成库的 Gradle 依靠将使 Glide 自动开始利用 Volley 来加载所有来自 http 和 https URL 的图片。
with源码剖析


  1. // with的重载的五个方法
  2. RequestManager with(Context context)
  3. RequestManager with(android.app.Activity)
  4. RequestManager with(android.app.Fragment)
  5. RequestManager with(android.support.v4.app.Fragment)
  6. RequestManager with(android.support.v4.app.FragmentActivity)
复制代码
  1. // grdle.java
  2. public static RequestManager with(@NonNull FragmentActivity activity) {
  3.     return getRetriever(activity).get(activity);
  4.   }
复制代码
RequestManager 主要两个作用:

  • 创建 RequestBuilder ;
  • 通过生命周期管理请求的启动竣事等。
getRetriever

getRetriever 方法通过传入 Context 获取 RequestManagerRetriever 的实例,然后通过该实例的 get 方法,终极返回一个 RequestManager 的实例。
   RequestManagerRetriever 是 Glide 用于管理和分发 RequestManager 实例的一个工具类
  1.   private static RequestManagerRetriever getRetriever(@Nullable Context context) {
  2.     //...
  3.         return Glide.get(context).getRequestManagerRetriever();
  4.     }
复制代码
调用 Glide.get(context).getRequestManagerRetriever():通过 Glide.get(context) 获取 Glide 的实例,然后调用 getRequestManagerRetriever() 方法获取 RequestManagerRetriever。
Glide.get

  1.   public static Glide get(@NonNull Context context) {
  2.     // 双层检测单例
  3.     if (glide == null) {
  4.       GeneratedAppGlideModule annotationGeneratedModule =
  5.           getAnnotationGeneratedGlideModules(context.getApplicationContext());
  6.       synchronized (Glide.class) {
  7.         if (glide == null) {
  8.           checkAndInitializeGlide(context, annotationGeneratedModule);
  9.         }
  10.       }
  11.     }
复制代码
返回 glide 实例:如果 Glide 已经被初始化,直接返回这个全局的 Glide 单例。
没有的话调用checkAndInitializeGlide方法,该方法最后会进入到下面方法:
initializeGlide

用于初始化Glide的单例
  1. @GuardedBy("Glide.class")
  2. private static void initializeGlide(
  3.       @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
  4.     initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
  5.   }
复制代码
  1. private static void initializeGlide(
  2.     @NonNull Context context,
  3.     @NonNull GlideBuilder builder,
  4.     @Nullable GeneratedAppGlideModule annotationGeneratedModule) {
  5.    
  6.     // 1. 获取应用的 ApplicationContext,确保在应用级别构建 Glide 实例,这样 Glide 可以全局使用
  7.     Context applicationContext = context.getApplicationContext();
  8.     // 2. 创建一个空的 GlideModule 列表。如果传入的 GeneratedAppGlideModuleImpl(注解生成的 GlideModule 实现类)为空
  9.     // 或者允许从 AndroidManifest 中解析 GlideModule 则解析 Manifest 文件获取 GlideModule 实例列表
  10.     List<GlideModule> manifestModules = Collections.emptyList();
  11.     if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
  12.         manifestModules = new ManifestParser(applicationContext).parse();
  13.     }
  14.     // 3. 如果传入的 GeneratedAppGlideModuleImpl 不为空且有需要排除的 GlideModule,则从解析出的 ManifestModule 列表中排除掉
  15.     if (annotationGeneratedModule != null
  16.         && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
  17.         Set<Class<?>> excludedModuleClasses = annotationGeneratedModule.getExcludedModuleClasses();
  18.         Iterator<GlideModule> iterator = manifestModules.iterator();
  19.         while (iterator.hasNext()) {
  20.             GlideModule current = iterator.next();
  21.             // 如果当前的 GlideModule 在排除列表中,则从 manifestModules 列表中移除
  22.             if (!excludedModuleClasses.contains(current.getClass())) {
  23.                 continue;
  24.             }
  25.             if (Log.isLoggable(TAG, Log.DEBUG)) {
  26.                 Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
  27.             }
  28.             iterator.remove();
  29.         }
  30.     }
  31.     // 4. 如果是调试模式,打印出从 AndroidManifest 中发现的所有 GlideModule 实例
  32.     if (Log.isLoggable(TAG, Log.DEBUG)) {
  33.         for (GlideModule glideModule : manifestModules) {
  34.             Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
  35.         }
  36.     }
  37.     // 5. 从注解生成的 GeneratedAppGlideModuleImpl 中获取 RequestManagerRetriever.RequestManagerFactory 工厂
  38.     // 用于创建 RequestManagerRetriever,这个工厂用于管理 Glide 图片加载的生命周期
  39.     RequestManagerRetriever.RequestManagerFactory factory =
  40.         annotationGeneratedModule != null
  41.             ? annotationGeneratedModule.getRequestManagerFactory()
  42.             : null;
  43.     // 6. 将工厂设置到 GlideBuilder 中,方便后续构建 Glide 时使用
  44.     builder.setRequestManagerFactory(factory);
  45.     // 7. 遍历 manifestModules 中的每一个 GlideModule,调用其 applyOptions 方法
  46.     // 让这些模块可以自定义 Glide 的配置选项
  47.     for (GlideModule module : manifestModules) {
  48.         module.applyOptions(applicationContext, builder);
  49.     }
  50.     // 8. 如果传入的 GeneratedAppGlideModuleImpl 不为空,调用其 applyOptions 方法
  51.     // 让注解生成的 GlideModule 实现类也可以自定义 Glide 的配置选项
  52.     if (annotationGeneratedModule != null) {
  53.         annotationGeneratedModule.applyOptions(applicationContext, builder);
  54.     }
  55.     // 9. 最终通过 GlideBuilder 使用构造者模式创建 Glide 实例,传递 applicationContext、解析出的 GlideModule 列表
  56.     // 以及注解生成的 GlideModule 实现类
  57.     Glide glide = builder.build(applicationContext, manifestModules, annotationGeneratedModule);
  58.     // 10. 将创建的 Glide 实例注册到 ApplicationContext 中,以便管理应用的生命周期回调
  59.     applicationContext.registerComponentCallbacks(glide);
  60.     // 11. 将构建出来的 Glide 实例赋值给 Glide 类的静态变量,这样全局都可以通过 Glide.get() 方法获取这个实例
  61.     Glide.glide = glide;
  62. }
复制代码
getRequestManagerRetriever

调用 Glide 的 getRequestManagerRetriver()就能拿到 RequestManagerRetriver对象
  1. public RequestManagerRetriever getRequestManagerRetriever() {
  2.   return requestManagerRetriever;
  3. }
复制代码
RequestManagerRetriever#get

拿到 RequestManagerRetriver对象后回到with方法中的调用get方法,获取 RequestManager 对象
get方法也要很多重载方法
  1. @NonNull
  2. public RequestManager get(@NonNull Context context) {
  3.     // 检查传入的 context 是否为 null,如果为 null 则抛出异常
  4.     if (context == null) {
  5.         throw new IllegalArgumentException("You cannot start a load on a null Context");
  6.     }
  7.     // 检查是在主线程并且context不是Application类型
  8.     else if (Util.isOnMainThread() && !(context instanceof Application)) {
  9.         if (context instanceof FragmentActivity) {
  10.             return get((FragmentActivity) context);
  11.         }
  12.         else if (context instanceof Activity) {
  13.             return get((Activity) context);
  14.         }
  15.         else if (context instanceof ContextWrapper
  16.             && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
  17.             return get(((ContextWrapper) context).getBaseContext());
  18.         }
  19.     }
  20.     // 子线程或context为application时
  21.     return getApplicationManager(context);
  22. }
复制代码
以进入FragmentActivity为例
  1. @NonNull
  2.   public RequestManager get(@NonNull FragmentActivity activity) {
  3.     // 判断当前是否为后台线程
  4.     if (Util.isOnBackgroundThread()) {
  5.       return get(activity.getApplicationContext());
  6.     } else {
  7.       assertNotDestroyed(activity);
  8.        // Glide 与 Fragment 的生命周期绑定
  9.       FragmentManager fm = activity.getSupportFragmentManager();
  10.       return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
  11.     }
  12.   }
复制代码
后台线程:
避免与特定活动的生命周期绑定,利用全局上下文来获取RequestManager,这样可以不受单个活动生命周期的影响。
主线程:
通过 FragmentManager 添加一个 RequestManagerFragment(隐藏的 Fragment)来管理图片加载请求的生命周期。例如,当 FragmentActivity 销毁时,RequestManagerFragment 能够取消所有未完成的图片加载请求,避免资源浪费
  1. private RequestManager supportFragmentGet(
  2.     @NonNull Context context,
  3.     @NonNull FragmentManager fm,
  4.     @Nullable Fragment parentHint,
  5.     boolean isParentVisible) {
  6.   // 获取当前 Activity 或 Fragment 关联的 SupportRequestManagerFragment
  7.   // 这就是隐藏的空白Fragment,用于管理 Glide 的 RequestManager 和生命周期
  8.   SupportRequestManagerFragment current =
  9.       getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
  10.   
  11.   // 检查是否已经存在一个与当前 Activity 或 Fragment 绑定的 RequestManager
  12.   RequestManager requestManager = current.getRequestManager();
  13.   
  14.   // 空白Fragment负责保存并复用RequestManager实例。,如果存在则直接复用,而不需要重新创建。
  15.   if (requestManager == null) {
  16.     // 获取全局 Glide 实例
  17.     Glide glide = Glide.get(context);
  18.    
  19.     // 使用 RequestManagerFactory 创建一个新的 RequestManager
  20.     // factory.build() 需要传入 Glide 实例、生命周期管理器、请求管理树节点和上下文
  21.     requestManager =
  22.         factory.build(
  23.             glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
  24.    
  25.     // 将创建的 RequestManager 绑定到当前的 SupportRequestManagerFragment 中,以便后续复用
  26.     current.setRequestManager(requestManager);
  27.   }
  28.   
  29.   // 返回这个 RequestManager,供 Glide 加载图片时使用
  30.   return requestManager;
  31. }
复制代码
空缺 Fragment 是一个不可见的 Fragment,它的任务是监听并相应宿主 Activity 或 Fragment 的生命周期变化。当宿主 Activity 或 Fragment 发生生命周期变化时,体系会自动调用 SupportRequestManagerFragment 的回调方法
SupportRequestManagerFragment 持有一个 ActivityFragmentLifecycle 实例,该类负责跟踪生命周期的变化,而且能够通知所有的生命周期监听器。
具体生命周期的监听流程:

  • 当宿主 Activity 或 Fragment 的生命周期发生变化时,空缺的 Fragment( SupportRequestManagerFragment)的相应生命周期回调方法会被自动触发。
  • 空缺 Fragment 生命周期方法会调用其内部的 ActivityFragmentLifecycle 对象的对应方法(如 onStart()、onStop()、onDestroy())。



  • ActivityFragmentLifecycle 会遍历 LifecycleListener 集合,依次调用每个监听器的生命周期方法(如 onStart()、onStop()、onDestroy())。
    ActivityFragmentLifecycle类:
  1. // 维护了一个 LifecycleListener 集合,并在生命周期事件(onStart, onStop, onDestroy)发生时通知所有监听器。
  2. class ActivityFragmentLifecycle implements Lifecycle {
  3.    
  4.      // 使用 WeakHashMap 来管理 LifecycleListener 集合,以防止内存泄漏。
  5.      private final Set<LifecycleListener> lifecycleListeners =
  6.          Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
  7.    
  8.      private boolean isStarted;
  9.      private boolean isDestroyed;
  10.    
  11.      // 添加一个新的 LifecycleListener 监听器。
  12.      @Override
  13.      public void addListener(@NonNull LifecycleListener listener) {
  14.        lifecycleListeners.add(listener);
  15.        if (isDestroyed) {
  16.          listener.onDestroy();
  17.        } else if (isStarted) {
  18.          listener.onStart();
  19.        } else {
  20.          listener.onStop();
  21.        }
  22.      }
  23.    
  24.      @Override
  25.      public void removeListener(@NonNull LifecycleListener listener) {
  26.        lifecycleListeners.remove(listener);
  27.      }
  28.    
  29.      // 当 Fragment 或 Activity 进入 onStart() 状态时调用。
  30.      void onStart() {
  31.        isStarted = true;
  32.        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
  33.          lifecycleListener.onStart();
  34.        }
  35.      }
  36.    
  37.      // 当 Fragment 或 Activity 进入 onStop() 状态时调用。
  38.      void onStop() {
  39.        isStarted = false;
  40.        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
  41.          lifecycleListener.onStop();
  42.        }
  43.      }
  44.    
  45.      // 当 Fragment 或 Activity 进入 onDestroy() 状态时调用。
  46.      void onDestroy() {
  47.        isDestroyed = true;
  48.        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
  49.          lifecycleListener.onDestroy();
  50.        }
  51.      }
  52.    }
复制代码

  • ActivityFragmentLifecycle 内部维护了一个 LifecycleListener 的集合,RequestManager 作为其中的一个监听器(即实现了 LifecycleListener 接口),会在这些生命周期变乱中被通知。
   RequestManager 实现了 LifecycleListener 接口,因此它能够在接收到生命周期变化通知时,执行其自身的生命周期管理逻辑:
  

  • 在 onStart() 中恢复停息的图片请求。
  • 在 onStop() 中停息正在举行的图片请求。
  • 在 onDestroy() 中取消所有的图片请求并开释资源,防止内存走漏。
  


   总结:
  

  • Activity 的生命周期改变(如进入前台时 onStart())。
  • Android 自动调用所有 Fragment 的 onStart() 方法,包罗隐藏的 SupportRequestManagerFragment。
  • SupportRequestManagerFragment 的 onStart() 方法被调用,进而调用 ActivityFragmentLifecycle 的 onStart() 方法。
  • ActivityFragmentLifecycle 遍历其持有的所有 LifecycleListener(如 RequestManager),调用它们的 onStart() 方法。
  • RequestManager 的 onStart() 方法被调用,恢复停息的图片请求。
  

感谢您的阅读
如有错误烦请指正


   参考:
  

  • Android—Glide的根本利用_android glide利用-CSDN博客
  • 【Android】Glide的简单利用(上)_android glide transition-CSDN博客
  • 【Android】Glide的简单利用(下)_glide override 会缓存吗-CSDN博客
  • Glide 源码剖析与原理总结——Glide.with - 技术栈 (jishuzhan.net)
  • 官方中文文档

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

星球的眼睛

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表