Glide基本用法及With方法源码解析

news2024/11/17 12:57:32

文章目录

  • 引入
    • 优点
  • 使用步骤
    • 导入依赖
    • 权限
    • 使用
  • 其他用法
    • 占位符
    • 错误图片
    • 后备回调符
    • 圆角
    • 过渡动画
    • 大小调整
    • gif
    • 缩略图
  • 使用RequestOptions
  • 缓存机制
    • 设置缓存策略
    • 清理缓存
  • 使用集成库
    • OkHttp
    • Volley
  • with源码解析
    • getRetriever
      • Glide.get
        • initializeGlide
      • getRequestManagerRetriever
    • RequestManagerRetriever#get

引入

Glide是一个快速高效的Android图片加载库

专门用来帮助开发者从网络、文件系统或应用资源中加载图片,并显示在 ImageView 或其他 UI 组件上。它具备高效的缓存机制和解码能力,能够处理图片、GIF、视频缩略图等多种媒体文件。

优点

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

使用步骤

导入依赖

    implementation 'com.github.bumptech.glide:glide:4.11.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

权限

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

使用

  1. 使用 Glide 加载本地图片并将其显示到 ImageView 中
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView image = findViewById(R.id.imageView);

        Glide.with(this)
                .load(R.drawable.a)
                .into(image);
    }
}
  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");
Glide.with(this).load(file).into(image);

image-20240925233751108

  1. Glide.with(this)
    • 这是 Glide 的入口,用于获取一个 RequestManager 实例,它负责后续的图片加载请求。
    • 参数 this 通常是当前的 ActivityFragment,表示 Glide 的生命周期将与该 ActivityFragment 绑定。这样可以确保在 ActivityFragment 销毁时,Glide 也会自动取消图片请求,避免内存泄漏。
  2. load(R.drawable.dp)
    • 这里的 load() 方法用来指定要加载的图片资源,获取到一个RequestManager实例,通过 RequestManager,Glide 可以自动管理图片的内存缓存和磁盘缓存,避免重复加载和浪费资源。RequestManager 提供了各种链式调用方法来配置加载选项,比如占位符、错误图片、缩放类型等。
    • 该方法也可以接收其他类型的参数,比如图片的 URL、文件路径、Bitmap 对象等。
  3. into(image)
    • into() 方法指定目标 ImageView,即将图片加载到哪个控件上。

其他用法

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

占位符

占位符是当请求正在执行时被展示的 Drawable 。

请求成功完成时,占位符会被请求到的资源替换。

如果被请求的资源是从内存中加载出来的,那么占位符可能根本不会被显示。

如果请求失败并且没有设置 error Drawable ,则占位符将被持续展示。

如果请求的url/model为 null ,并且 error Drawablefallback 都没有设置,那么占位符也会继续显示。

错误图片

error Drawable 在请求永久性失败时展示。

error Drawable 在请求的url/model为 null ,且并没有设置 fallback Drawable 时展示。

Glide.with(this)
        .load("https://i1.hdslb.com/bfs/archive/bea5b65f3328a6027ca6ab173c3e3ccaa98f5d21.jpg")
        .placeholder(R.drawable.img_loading) // 占位图
        .error(R.drawable.img_error) // 错误显示图片
        .into(image);
  • 占位符是在主线程从Android Resources加载的

后备回调符

fallback Drawable 在请求的url/model为 null 时展示。目的是允许用户指示 null 是否为可接受的正常情况。

例如,一个用户的个人资料 URL 为 null,这可能意味着用户没有设置头像。在这种情况下,应该使用默认头像。

默认情况下Glide将 null 作为错误处理,所以可以接受 null 的应用应当显式地设置一个 fallback Drawable

Glide.with(fragment)
  .load(url)
  .fallback(R.drawable.fallback)
  .into(view);

圆角

Glide.with(this)
                .load("https://i0.hdslb.com/bfs/archive/d04368506b906a0d4ac62217e93467cdaa29af90.jpg")
                .placeholder(R.drawable.img_loading) 
                .error(R.drawable.img_error) 
                .transform(new CircleCrop())// 裁剪为圆形
                .into(image);
Glide.with(this)
                .load("https://i0.hdslb.com/bfs/archive/d04368506b906a0d4ac62217e93467cdaa29af90.jpg")
                .placeholder(R.drawable.img_loading)
                .error(R.drawable.img_error) 
                .transform(new RoundedCorners(200)) //圆角
                .into(image);

过渡动画

TransitionOptions用于决定你的加载完成时会发生什么

可以应用以下变换:

  • View淡入
  • 与占位符交叉淡入
  • 或者什么都不发生

与占位符交叉淡入效果:

Glide.with(context)
     .load(imageUrl)
     .transition(DrawableTransitionOptions.withCrossFade()) // 使用淡入淡出效果
     .into(imageView);

自定义过渡动画:

如果需要自定义过渡动画,可以使用 TransitionOptions 类和 Glide 的 RequestOptions 结合使用。可以通过 TransitionDrawable 或其他动画效果进行实现。

Glide.with(context)
     .load(imageUrl)
     .transition(GenericTransitionOptions.with(R.anim.zoom_in)) // 使用自定义动画
     .into(imageView);

大小调整

  1. override()

override(width, height) 方法可以让你明确指定加载图片的宽度和高度,强制 Glide 调整图片大小。

Glide.with(context)
     .load(imageUrl)
     .override(300, 200) // 将图片调整为 300x200 像素
     .into(imageView);
  1. fitCenter()

fitCenter() 方法会将图片等比例缩放到 ImageView 中,确保整个图片都能显示出来,而不裁剪图片。

Glide.with(context)
     .load(imageUrl)
     .fitCenter() // 等比例缩放,确保整个图片适应 ImageView
     .into(imageView);
  1. centerCrop()

centerCrop() 方法会将图片等比例缩放并裁剪,确保填满整个 ImageView。如果图片的比例与 ImageView 不符,图片的边缘会被裁剪掉。

Glide.with(context)
     .load(imageUrl)
     .centerCrop() // 裁剪并填充 ImageView
     .into(imageView);
  1. scale()

如果需要手动控制缩放因子,可以使用 scale() 方法来实现。这个方法允许你通过传入缩放因子来调整图片。

Glide.with(context)
     .load(imageUrl)
     .scale(0.5f) // 将图片缩放至原始大小的 50%
     .into(imageView);

gif

  • 加载 GIF

如果你想强制将 GIF 作为动画加载,可以使用 asGif() 方法:

Glide.with(this)
    .load("https://pa1.narvii.com/7938/29d490319494e7cc1b4713464a64ce8b35a22099r1-498-446_hq.gif")
    .into(image);
  • 将 GIF 当作 Bitmap 显示
Glide.with(this)
    .asBitmap()
    .load(gifUrl)
    .into(image);
  • 显示本地视频缩略图

要从本地视频文件中加载缩略图,你可以使用以下代码:

String filePath = "/storage/emulated/0/Pictures/targetVideo.mp4";

GlideApp  
    .with(context)
    .asBitmap()  // 加载为 Bitmap
    .load(Uri.fromFile(new File(filePath)))  // 指向本地视频文件的 URI
    .into(imageViewGifAsBitmap);  // 目标 ImageView

缩略图

在加载主图像时同时加载其低分辨率的缩略图。提升用户体验,减少用户等待加载主图像时看到空白或加载指示器的时间。

  • thumbnail() 允许你为主请求指定一个缩略图请求,这样在主图像加载期间会先展示缩略图,提升用户体验
  1. 加载远程图像和缩略图
Glide.with(fragment)
  .load(url)  // 主图像的 URL
  .thumbnail(Glide.with(fragment)
    .load(thumbnailUrl))  // 缩略图的 URL
  .into(imageView);
  • 注意:确保 thumbnailUrl 指向的图片分辨率低于主 URL 指向的图片。
  1. 加载本地图像和缩略图
int thumbnailSize = 100; // 指定缩略图的大小

Glide.with(fragment)
  .load(localUri)  // 主图像的本地 URI
  .thumbnail(Glide.with(fragment)
    .load(localUri)  // 再次加载相同的本地图像
    .override(thumbnailSize))  // 强制设置缩略图的尺寸
  .into(imageView);

使用RequestOptions

  • 想让你的应用的不同部分之间共享相同的加载选项,你也可以初始化一个新的 RequestOptions 对象,并在每次加载时通过 apply() 方法传入这个对象:

RequestOptions 是一个类,用来配置图片加载请求的各种选项。通过它可以更加灵活地定制图片加载过程,包括设置占位符、错误图片、图片缩放方式、裁剪模式、缓存策略等。

RequestOptions requestOptions = new RequestOptions()
        .placeholder(R.drawable.img_loading) // 占位图
        .error(R.drawable.img_error) // 错误显示图片

ImageView image = findViewById(R.id.imageView);
Glide.with(this)
        .load("https://i1.hdslb.com/bfs/archive/bea5b65f3328a6027ca6ab173c3e3ccaa98f5d21.jpg")
        .apply(requestOptions)
        .into(image);

apply()方法可以被调用多次,因此 RequestOption 可以被组合使用。如果 RequestOptions 对象之间存在相互冲突的设置,那么只有最后一个被应用的 RequestOptions 会生效。

缓存机制

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

  1. 内存缓存

    • 内存缓存用于快速加载已经加载过的图像,避免重复下载。这可以显著提高图像的显示速度。
    • 默认情况下,Glide 会在内存中缓存加载的图像
  2. 磁盘缓存

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

默认会使用内存和硬盘缓存

设置缓存策略

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

  • 跳过内存缓存
    禁用内存缓存,使用 skipMemoryCache(true)

    Glide.with(context)
        .load(imageUrl)
        .skipMemoryCache(true)  // 跳过内存缓存
        .into(imageView);
    
  • 自定义磁盘缓存策略

    Glide.with(context)
        .load(imageUrl)
        .diskCacheStrategy(DiskCacheStrategy.ALL)  // 缓存所有版本的图像
        .into(imageView);
    

磁盘缓存策略选项

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

清理缓存

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

  • 清理内存缓存

    Glide.get(context).clearMemory();
    
  • 清理磁盘缓存

    new Thread(new Runnable() {
        @Override
        public void run() {
            Glide.get(context).clearDiskCache();
        }
    }).start();
    

使用集成库

OkHttp

添加一个对 OkHttp 集成库的依赖:

compile "com.github.bumptech.glide:okhttp3-integration:4.11.0"

添加 OkHttp 集成库的 Gradle 依赖将使 Glide 自动开始使用 OkHttp 来加载所有来自 http 和 https URL 的图片。

Volley

compile "com.github.bumptech.glide:volley-integration:4.11.0"

添加 Volley 集成库的 Gradle 依赖将使 Glide 自动开始使用 Volley 来加载所有来自 http 和 https URL 的图片。

with源码解析

image-20240925233751108

// with的重载的五个方法
RequestManager with(Context context)
RequestManager with(android.app.Activity)
RequestManager with(android.app.Fragment)
RequestManager with(android.support.v4.app.Fragment)
RequestManager with(android.support.v4.app.FragmentActivity)
// grdle.java

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

RequestManager 主要两个作用:

  1. 创建 RequestBuilder ;
  2. 通过生命周期管理请求的启动结束等。

getRetriever

getRetriever 方法通过传入 Context 获取 RequestManagerRetriever 的实例,然后通过该实例的 get 方法,最终返回一个 RequestManager 的实例。

RequestManagerRetriever 是 Glide 用于管理和分发 RequestManager 实例的一个工具类

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

调用 Glide.get(context).getRequestManagerRetriever():通过 Glide.get(context) 获取 Glide 的实例,然后调用 getRequestManagerRetriever() 方法获取 RequestManagerRetriever

Glide.get

  public static Glide get(@NonNull Context context) {
    // 双层检测单例
    if (glide == null) {
      GeneratedAppGlideModule annotationGeneratedModule =
          getAnnotationGeneratedGlideModules(context.getApplicationContext());
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context, annotationGeneratedModule);
        }
      }
    }

返回 glide 实例:如果 Glide 已经被初始化,直接返回这个全局的 Glide 单例。

没有的话调用checkAndInitializeGlide方法,该方法最后会进入到下面方法:

initializeGlide

用于初始化Glide的单例

 @GuardedBy("Glide.class")
 private static void initializeGlide(
      @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
    initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
  }

private static void initializeGlide(
    @NonNull Context context,
    @NonNull GlideBuilder builder,
    @Nullable GeneratedAppGlideModule annotationGeneratedModule) {
    
    // 1. 获取应用的 ApplicationContext,确保在应用级别构建 Glide 实例,这样 Glide 可以全局使用
    Context applicationContext = context.getApplicationContext();

    // 2. 创建一个空的 GlideModule 列表。如果传入的 GeneratedAppGlideModuleImpl(注解生成的 GlideModule 实现类)为空
    // 或者允许从 AndroidManifest 中解析 GlideModule 则解析 Manifest 文件获取 GlideModule 实例列表
    List<GlideModule> manifestModules = Collections.emptyList();
    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
        manifestModules = new ManifestParser(applicationContext).parse();
    }

    // 3. 如果传入的 GeneratedAppGlideModuleImpl 不为空且有需要排除的 GlideModule,则从解析出的 ManifestModule 列表中排除掉
    if (annotationGeneratedModule != null
        && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
        Set<Class<?>> excludedModuleClasses = annotationGeneratedModule.getExcludedModuleClasses();
        Iterator<GlideModule> iterator = manifestModules.iterator();
        while (iterator.hasNext()) {
            GlideModule current = iterator.next();
            // 如果当前的 GlideModule 在排除列表中,则从 manifestModules 列表中移除
            if (!excludedModuleClasses.contains(current.getClass())) {
                continue;
            }
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
            }
            iterator.remove();
        }
    }

    // 4. 如果是调试模式,打印出从 AndroidManifest 中发现的所有 GlideModule 实例
    if (Log.isLoggable(TAG, Log.DEBUG)) {
        for (GlideModule glideModule : manifestModules) {
            Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
        }
    }

    // 5. 从注解生成的 GeneratedAppGlideModuleImpl 中获取 RequestManagerRetriever.RequestManagerFactory 工厂
    // 用于创建 RequestManagerRetriever,这个工厂用于管理 Glide 图片加载的生命周期
    RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory()
            : null;

    // 6. 将工厂设置到 GlideBuilder 中,方便后续构建 Glide 时使用
    builder.setRequestManagerFactory(factory);

    // 7. 遍历 manifestModules 中的每一个 GlideModule,调用其 applyOptions 方法
    // 让这些模块可以自定义 Glide 的配置选项
    for (GlideModule module : manifestModules) {
        module.applyOptions(applicationContext, builder);
    }

    // 8. 如果传入的 GeneratedAppGlideModuleImpl 不为空,调用其 applyOptions 方法
    // 让注解生成的 GlideModule 实现类也可以自定义 Glide 的配置选项
    if (annotationGeneratedModule != null) {
        annotationGeneratedModule.applyOptions(applicationContext, builder);
    }

    // 9. 最终通过 GlideBuilder 使用构造者模式创建 Glide 实例,传递 applicationContext、解析出的 GlideModule 列表
    // 以及注解生成的 GlideModule 实现类
    Glide glide = builder.build(applicationContext, manifestModules, annotationGeneratedModule);

    // 10. 将创建的 Glide 实例注册到 ApplicationContext 中,以便管理应用的生命周期回调
    applicationContext.registerComponentCallbacks(glide);

    // 11. 将构建出来的 Glide 实例赋值给 Glide 类的静态变量,这样全局都可以通过 Glide.get() 方法获取这个实例
    Glide.glide = glide;
}

getRequestManagerRetriever

调用 Glide 的 getRequestManagerRetriver()就能拿到 RequestManagerRetriver对象

public RequestManagerRetriever getRequestManagerRetriever() {
  return requestManagerRetriever;
}

RequestManagerRetriever#get

拿到 RequestManagerRetriver对象后回到with方法中的调用get方法,获取 RequestManager 对象

get方法也要很多重载方法

@NonNull
public RequestManager get(@NonNull Context context) {
    // 检查传入的 context 是否为 null,如果为 null 则抛出异常
    if (context == null) {
        throw new IllegalArgumentException("You cannot start a load on a null Context");
    }
    // 检查是在主线程并且context不是Application类型
    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());
        }
    }
    // 子线程或context为application时
    return getApplicationManager(context);
}

以进入FragmentActivity为例

 @NonNull
  public RequestManager get(@NonNull FragmentActivity activity) {
    // 判断当前是否为后台线程
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
       // Glide 与 Fragment 的生命周期绑定
      FragmentManager fm = activity.getSupportFragmentManager();
      return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

后台线程:

避免与特定活动的生命周期绑定,使用全局上下文来获取RequestManager,这样可以不受单个活动生命周期的影响。

主线程:

通过 FragmentManager 添加一个 RequestManagerFragment(隐藏的 Fragment)来管理图片加载请求的生命周期。例如,当 FragmentActivity 销毁时,RequestManagerFragment 能够取消所有未完成的图片加载请求,避免资源浪费

private RequestManager supportFragmentGet(
    @NonNull Context context,
    @NonNull FragmentManager fm,
    @Nullable Fragment parentHint,
    boolean isParentVisible) {

  // 获取当前 Activity 或 Fragment 关联的 SupportRequestManagerFragment
  // 这就是隐藏的空白Fragment,用于管理 Glide 的 RequestManager 和生命周期
  SupportRequestManagerFragment current =
      getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
  
  // 检查是否已经存在一个与当前 Activity 或 Fragment 绑定的 RequestManager
  RequestManager requestManager = current.getRequestManager();
  
  // 空白Fragment负责保存并复用RequestManager实例。,如果存在则直接复用,而不需要重新创建。
  if (requestManager == null) {
    // 获取全局 Glide 实例
    Glide glide = Glide.get(context);
    
    // 使用 RequestManagerFactory 创建一个新的 RequestManager
    // factory.build() 需要传入 Glide 实例、生命周期管理器、请求管理树节点和上下文
    requestManager =
        factory.build(
            glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
    
    // 将创建的 RequestManager 绑定到当前的 SupportRequestManagerFragment 中,以便后续复用
    current.setRequestManager(requestManager);
  }
  
  // 返回这个 RequestManager,供 Glide 加载图片时使用
  return requestManager;
}

空白 Fragment 是一个不可见的 Fragment,它的任务是监听并响应宿主 ActivityFragment 的生命周期变化。当宿主 ActivityFragment 发生生命周期变化时,系统会自动调用 SupportRequestManagerFragment 的回调方法

SupportRequestManagerFragment 持有一个 ActivityFragmentLifecycle 实例,该类负责跟踪生命周期的变化,并且能够通知所有的生命周期监听器。

具体生命周期的监听流程:

  1. 当宿主 ActivityFragment 的生命周期发生变化时,空白的 FragmentSupportRequestManagerFragment)的相应生命周期回调方法会被自动触发。

  2. 空白 Fragment 生命周期方法会调用其内部的 ActivityFragmentLifecycle 对象的对应方法(如 onStart()onStop()onDestroy())。

image-20240927220655515

image-20240927220618146

  1. ActivityFragmentLifecycle 会遍历 LifecycleListener 集合,依次调用每个监听器的生命周期方法(如 onStart()onStop()onDestroy())。

    ActivityFragmentLifecycle类:

// 维护了一个 LifecycleListener 集合,并在生命周期事件(onStart, onStop, onDestroy)发生时通知所有监听器。
class ActivityFragmentLifecycle implements Lifecycle {
   
     // 使用 WeakHashMap 来管理 LifecycleListener 集合,以防止内存泄漏。
     private final Set<LifecycleListener> lifecycleListeners =
         Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
   
     private boolean isStarted;
     private boolean isDestroyed;
   
     // 添加一个新的 LifecycleListener 监听器。
     @Override
     public void addListener(@NonNull LifecycleListener listener) {
       lifecycleListeners.add(listener);
       if (isDestroyed) {
         listener.onDestroy();
       } else if (isStarted) {
         listener.onStart();
       } else {
         listener.onStop();
       }
     }
   
     @Override
     public void removeListener(@NonNull LifecycleListener listener) {
       lifecycleListeners.remove(listener);
     }
   
     // 当 Fragment 或 Activity 进入 onStart() 状态时调用。
     void onStart() {
       isStarted = true;
       for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
         lifecycleListener.onStart();
       }
     }
   
     // 当 Fragment 或 Activity 进入 onStop() 状态时调用。
     void onStop() {
       isStarted = false;
       for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
         lifecycleListener.onStop();
       }
     }
   
     // 当 Fragment 或 Activity 进入 onDestroy() 状态时调用。
     void onDestroy() {
       isDestroyed = true;
       for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
         lifecycleListener.onDestroy();
       }
     }
   }
  1. ActivityFragmentLifecycle 内部维护了一个 LifecycleListener 的集合,RequestManager 作为其中的一个监听器(即实现了 LifecycleListener 接口),会在这些生命周期事件中被通知。

RequestManager 实现了 LifecycleListener 接口,因此它能够在接收到生命周期变化通知时,执行其自身的生命周期管理逻辑:

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

image-20240927215259897

image-20240927220917251

总结:

  1. Activity 的生命周期改变(如进入前台时 onStart())。
  2. Android 自动调用所有 FragmentonStart() 方法,包括隐藏的 SupportRequestManagerFragment
  3. SupportRequestManagerFragmentonStart() 方法被调用,进而调用 ActivityFragmentLifecycleonStart() 方法。
  4. ActivityFragmentLifecycle 遍历其持有的所有 LifecycleListener(如 RequestManager),调用它们的 onStart() 方法。
  5. RequestManageronStart() 方法被调用,恢复暂停的图片请求。


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


参考:

  1. Android—Glide的基本使用_android glide使用-CSDN博客
  2. 【Android】Glide的简单使用(上)_android glide transition-CSDN博客
  3. 【Android】Glide的简单使用(下)_glide override 会缓存吗-CSDN博客
  4. Glide 源码解析与原理总结——Glide.with - 技术栈 (jishuzhan.net)
  5. 官方中文文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2173542.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VS Code breadcrumbs view 是什么

VS Code breadcrumbs view 是什么 正文 正文 breadcrumbs view&#xff1a;中文翻译&#xff0c;面包屑视图&#xff0c;乍听起来感觉十分抽象。这里我们来解释一下这个视图的含义&#xff1f; 如下图所示&#xff0c;红色框标记的部分就是 这个视图可以显示出当前打卡文件所…

深入理解 Nuxt.js 中的 app:error:cleared 钩子

title: 深入理解 Nuxt.js 中的 app:error:cleared 钩子 date: 2024/9/28 updated: 2024/9/28 author: cmdragon excerpt: Nuxt.js 中的 app:error:cleared 钩子的用途及其实现方式。这个钩子为开发者提供了一种优雅的方式来处理错误清除后的状态恢复和用户反馈。 categor…

Rust赋能前端:为WebAssembly 瘦身

❝ 凡事你一旦接纳了&#xff0c;就不存在了&#xff1b;你看不惯它&#xff0c;它就一直折磨你 大家好&#xff0c;我是柒八九。一个专注于前端开发技术/Rust及AI应用知识分享的Coder ❝ 此篇文章所涉及到的技术有 WebAssembly Rust SIMD LLVM binaryen 因为&#xff0c;行文字…

大数据-151 Apache Druid 集群模式 配置启动【上篇】 超详细!

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

windows10 docker 推送本地镜像

windows10安装好docker后&#xff0c;接下来上传本地镜像文件&#xff1a; 1&#xff0c;设置请非安全参数&#xff0c;处理&#xff1a;https改为http请求 点击设置&#xff0c;打开 Docker Engine 追加&#xff1a; "insecure-registries": ["http://177.18…

8-回溯算法

参考 代码随想录 题目分类大纲如下&#xff1a; 一、回溯算法理论基础 1、什么是回溯法 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。回溯是递归的副产品&#xff0c;只要有递归就会有回溯。回溯法其实就是暴力查找&#xff0c;并不是什么高效的算法 2、回…

分享了一个支持WIN7的QGIS3.34的版本

上传分享了一个支持WIN7的QGIS3.34的版本&#xff0c;该版本同时也是个轻量级的QGIS&#xff0c;大小轻便、启动速度也快&#xff01;但该版本没有Python及Python插件支持。 需要在WIN7下使用或只使用QGIS3.34核心基本功能的可以使用这个&#xff01;当然这个版本也支持WIN7以上…

Docker必学命令与操作技巧:新手快速入门指南

各位Docker初学者大家好!今天为大家分享一些关于Docker的必学命令和操作技巧,帮助大家快速入门。 Docker是什么? Docker是一个开源的容器化平台,它可以让开发者打包他们的应用以及依赖项到一个轻量级、可移植的容器中,然后在任何运行Docker引擎的机器上运行。 必学Dock…

使用Python创建EXE运行器和截图工具

在今天的博客中,我们将探讨如何使用Python和wxPython创建一个强大而实用的桌面应用程序。这个应用程序可以遍历指定文件夹中的所有EXE文件,并提供运行这些文件和自动截图的功能。无论你是系统管理员、软件测试人员,还是仅仅对自动化工具感兴趣的开发者,这个项目都会给你带来启发…

低代码用户中心:构建高效便捷的用户管理平台

什么是低代码用户中心&#xff1f; 低代码用户中心是一种利用低代码开发平台构建的用户管理系统&#xff0c;允许企业快速创建、部署和管理用户信息、权限及互动记录。通过可视化界面和预置组件&#xff0c;企业可以在短时间内实现灵活的用户管理解决方案&#xff0c;而无需编…

美畅物联丨GB/T 28181系列之TCP/UDP被动模式和TCP主动模式

GB/T 28181《安全防范视频监控联网系统信息传输、交换、控制技术要求》作为我国安防领域的重要标准&#xff0c;为视频监控系统的建设提供了全面的技术指导和规范。该标准详细规定了视频监控系统的信息传输、交换和控制技术要求&#xff0c;在视频流传输方面&#xff0c;GB/T 2…

【Midjourney中文版:AI绘画新纪元,赋能创意设计与开发】

在数字艺术与设计领域&#xff0c;创新与效率并重。Midjourney中文版&#xff0c;作为一款强大的AI绘画工具&#xff0c;正引领我们步入一个全新的创意时代。它不仅简化了复杂的绘画流程&#xff0c;更以智能算法为驱动力&#xff0c;为开发者、设计师及所有创意工作者带来了前…

从0开始深度学习(6)——Pytorch动态图机制(前向传播、反向传播)

PyTorch 的动态计算图机制是其核心特性之一&#xff0c;它使得深度学习模型的开发更加灵活和高效。 0 计算图 计算图&#xff08;Computation Graph&#xff09;是一种用于表示数学表达式或程序流程的图形结构&#xff0c;可以将复杂的表达式分解成一系列简单的操作&#xff0…

Materials Studio零基础专题培训重磅来袭

一、软件介绍 Materials Studio是一款由美国Accelrys公司开发的新一代材料计算软件&#xff0c;专为材料科学领域的研究者设计&#xff0c;能够运行在PC上进行各种模拟研究。以下是对它的具体介绍&#xff1a; 1. 软件简介 定义与用途&#xff1a;Materials Studio是一款专门…

基于SpringBoot+Vue的智慧博物馆管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

MapReduce学习与理解

MapReduce为google分布式三驾马车之一。分别为《The Google File System》、《MapReduce: Simplified Data Processing on Large Clusters》、《Bigtable: A Distributed Storage System for Structured Data》。三遍论文奠定了分布式存储和计算的基础。本篇文章来说说mapreduc…

在 commit 里使用 emoji~

在 git commit 上使用 emoji 提供了一种简单的方法&#xff1a;仅通过查看所使用的 emoji 来确定提交的目的或意图&#xff0c;非常好理解&#xff0c;阅读体验很棒。 ‍ 效果 以我的 博客项目 为例&#xff0c;可以看到不少的 emoji &#xff1a; ‍ ‍ 使用方法 直接在…

【Linux】驱动的基本架构和编译

驱动源码 /** Silicon Integrated Co., Ltd haptic sih688x haptic driver file** Copyright (c) 2021 kugua <daokuan.zhusi-in.com>** This program is free software; you can redistribute it and/or modify it* under the terms of the GNU General Public Licen…

python基础库

文章目录 1.研究目的2.platform库介绍3.代码4.结果展示 1.研究目的 最近项目中需要利用python获取计算机硬件的一些基本信息,查阅资料,.于是写下这篇简短的博客,有问题烦请提出,谢谢-_- 2.platform库介绍 platform 库是 Python 的一个内置库&#xff0c;可以让我们轻松地获取…

京东面试:RR隔离mysql如何实现?什么情况RR不能解决幻读?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 谈谈&#xff1a;mysql 事务隔离的底层原理&#xff1…