当前位置: 首页 > news >正文

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

文章目录

  • 引入
    • 优点
  • 使用步骤
    • 导入依赖
    • 权限
    • 使用
  • 其他用法
    • 占位符
    • 错误图片
    • 后备回调符
    • 圆角
    • 过渡动画
    • 大小调整
    • 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 {@Overrideprotected 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() {@Overridepublic 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.javapublic 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为例

 @NonNullpublic 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 绑定的 RequestManagerRequestManager 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 监听器。@Overridepublic void addListener(@NonNull LifecycleListener listener) {lifecycleListeners.add(listener);if (isDestroyed) {listener.onDestroy();} else if (isStarted) {listener.onStart();} else {listener.onStop();}}@Overridepublic 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. 官方中文文档

相关文章:

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

文章目录 引入优点 使用步骤导入依赖权限使用 其他用法占位符错误图片后备回调符圆角过渡动画大小调整gif缩略图 使用RequestOptions缓存机制设置缓存策略清理缓存 使用集成库OkHttpVolley with源码解析getRetrieverGlide.getinitializeGlide getRequestManagerRetriever Reque…...

html中的文本标签(含标签的实现案例)

目录 1.标题标签 2.标题标签的align属性 3.段落标签 4.水平线标签hr 5.换行标签br 6.文本样式标签font ​编辑7.文本格式化标签 8.文本语义标签 1&#xff09;时间time标签 2&#xff09;文本高亮Mark标签 3&#xff09;cite标签 9.特殊字符标签 10.图像标签img 附录&#xff…...

通信协议感悟

本文结合个人所学&#xff0c;简要讲述SPI&#xff0c;I2C&#xff0c;UART通信的特点&#xff0c;限制。 1.同步通信 UART&#xff0c;SPI&#xff0c;I2C三种串行通讯方式&#xff0c;SPI功能引脚为CS&#xff0c;CLK&#xff0c;MOSI&#xff0c;MISO&#xff1b;I2C功能引…...

IDEA几大常用AI插件

文章目录 前言列表GPT中文版TalkXBito AIIDEA自带的AI 前言 最近AI、GPT特别火&#xff0c;IDEA里面又有一堆插件支持GPT&#xff0c;所以做个专题比较一下各个GPT插件 列表 先看idea的plugins里支持哪些&#xff0c;搜索“GPT”之后得到的&#xff0c;我用下来感觉第一第二和…...

51单片机学习第六课---B站UP主江协科技

DS18B20 1、基本知识讲解 2、DS18B20读取温度值 main.c #include<regx52.h> #include"delay.h" #include"LCD1602.h" #include"key.h" #include"DS18B20.h"float T; void main () {LCD_Init();LCD_ShowString(1,1,"temp…...

sadTalker本地编译

SadTalker一款开源的可生成逼真的人像动画的工具。它利用深度学习技术&#xff0c;根据输入的图像和音频&#xff0c;生成具有生动表情和动作的视频。用户可以通过上传照片或使用预设的模型&#xff0c;轻松创建个性化的动画内容. 以上是官网的图, 下边是本地部署生成的,效果差…...

强化学习核心概念与公式总结

强化学习核心概念与公式总结 1. 核心概念 1.1 智能体(Agent)和环境(Environment) 智能体:学习和做决策的实体环境:智能体交互的外部系统1.2 状态(State) 描述环境在特定时刻的情况1.3 动作(Action) 智能体可以执行的操作1.4 奖励(Reward) 环境对智能体动作的即时反馈1.5 策…...

基础算法--双指针【概念+图解+题解+解释】

更多精彩内容..... &#x1f389;❤️播主の主页✨&#x1f618; Stark、-CSDN博客 本文所在专栏&#xff1a; 数据结构与算法_Stark、的博客-CSDN博客 其它专栏&#xff1a; 学习专栏C语言_Stark、的博客-CSDN博客 项目实战C系列_Stark、的博客-CSDN博客​​​​​​ 座右铭&a…...

国产化系统/鸿蒙开发足浴店收银源码-收缩左侧———未来之窗行业应用跨平台架构

一、左侧展开后 二、代码 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head><title></title><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"><style t…...

如何从硬盘恢复丢失/删除的视频

您是否想知道是否可以恢复已删除的视频&#xff1f; 幸运的是&#xff0c;您可以使用奇客数据恢复从硬盘驱动器、SD 卡和 USB 闪存驱动器恢复已删除的视频文件。 你有没有遇到过这样的情况&#xff1a;当你随机删除文件以释放空间时&#xff0c;你不小心按下了一些重要视频的…...

《Effective C++》第三版——设计与声明(1)

参考资料&#xff1a; 《Effective C》第三版 注意&#xff1a;《Effective C》不涉及任何 C11 的内容&#xff0c;因此其中的部分准则可能在 C11 出现后有更好的实现方式。 条款 18&#xff1a;让接口容易被正确使用&#xff0c;不易被误用 好的接口很容易被正确使用&…...

数值计算的程序设计问题举例

### 数值计算的程序设计问题 #### 1. 结构静力分析计算 **涉及领域**&#xff1a;工程力学、建筑工程 **主要问题**&#xff1a;线性代数方程组&#xff08;Linear Algebraic Equations&#xff09; **解释说明**&#xff1a; 在结构静力分析中&#xff0c;我们需要解决复杂的…...

Java之方法的使用

修饰符 返回值 方法名称&#xff08;形式参数&#xff09;{ } 当无参数的时候形式参数中什么都不写。 列如求两个数相加 修饰符可有可无。 方法重载&#xff1a; 1.方法名相同 2.参数列表不同 3。返回值不影响重载...

sudo 命令:掌握系统权限控制,实现安全高效管理

一、命令简介 ​sudo​ 命令允许系统管理员授权普通用户执行特定命令&#xff0c;并以管理员身份运行这些命令&#xff0c;通常需要输入用户自己的密码。 ​​ sudo 全称是"substitute user do"&#xff0c;意为“替用户做”&#xff0c;也就是“以另一个用户的身…...

AndroidStudio导入so文件

点击app 右键依次选择New-Floder-JNI Floder 创建jni目录 将需要的so文件拷贝到jni目录 在app目录下&#xff0c;build.gradle文件的android{}中添加&#xff1a; sourceSets {main{jniLibs.srcDirs [src/main/jni]}}点击一下Sync Project with Gradle Files 然后编译生成AP…...

Kuebernetes 群集基于 Docker 部署

Kuebernetes 群集基于 Docker 部署 实验报告资源列表基础环境一、准备 Docker1、安装 Docker 二、安装 Kubeadm 工具1、配置 yum 源2、安装 Kubeadm 工具 三、初始化 Master 节点1、配置 Master 节点2、常见故障 四、Node 节点加入集群五、部署网络插件&#xff08;CNI&#xf…...

追随 HarmonyOS NEXT,Solon v3.0 将在10月8日发布

Solon &#xff08;开放原子开源基金会&#xff0c;孵化项目&#xff09;原计划10月1日发布 v3.0 正式版。看到 HarmonyOS NEXT 将在 10月8日启用公测&#xff0c;现改为10月8日发布以示庆贺。另外&#xff0c;Solon 将在2025年启动“仓颉”版开发&#xff08;届时&#xff0c;…...

服装时尚与动漫游戏的跨界联动:创新运营与策划策略研究

摘要&#xff1a;本论文聚焦于服装时尚与动漫游戏的跨界联动现象&#xff0c;深入探讨其在运营和策划方向的策略与实践。通过对相关理论的梳理和实际案例的分析&#xff0c;阐述了跨界联动的背景、意义、模式以及面临的挑战。研究发现&#xff0c;成功的跨界联动能够实现品牌价…...

Redis中String类型的常用命令(append,getrenge,setrange等命令)

Redis----String命令 前言.常见的String存储类型. 常见命令1. set 命令2. get 命令3. mget命令与mset命令4. setnx命令5. setex与psetex命令6. incr与incrby与incrbyfloat命令7. decr与decrby命令8. append命令9. getrange和setrange命令10. strlen命令. 前言. 常见的String存…...

深度拆解:如何在Facebook上做跨境电商?

国内社交媒体正在逐渐兴盛&#xff0c;海外也不例外。在数字营销的新时代&#xff0c;Facebook已成为跨境电商不可或缺的平台之一。通过Facebook的巨大流量&#xff0c;卖家可以更好的触及潜在消费者&#xff0c;以实现销售增长。本文就深度拆解一下&#xff0c;卖家如何利用Fb…...

为啥数据需转换成tensor才能参与后续建模训练

将数据转换为Tensor&#xff08;张量&#xff09;格式用于深度学习和机器学习模型训练&#xff0c;主要是出于以下几个关键原因&#xff1a; 数值计算的效率&#xff1a;Tensor&#xff08;由PyTorch、TensorFlow等库提供&#xff09;是在GPU上执行高效的数值运算的数据结构。相…...

leetcode:380. O(1) 时间插入、删除和获取随机元素

实现RandomizedSet 类&#xff1a; RandomizedSet() 初始化 RandomizedSet 对象bool insert(int val) 当元素 val 不存在时&#xff0c;向集合中插入该项&#xff0c;并返回 true &#xff1b;否则&#xff0c;返回 false 。bool remove(int val) 当元素 val 存在时&#xff0…...

Linux集群部署RabbitMQ

目录 一、准备三台虚拟机&#xff0c;配置相同 1、所有主机都需要hosts文件解析 2、所有主机安装erLang和rabbitmq 3、修改配置文件 4、导入rabbitmq 的管理界面 5、查看节点状态 6、设置erlang运行节点 7、rabitmq2和rabbitmq3重启服务 8、查看各个节点状态 二、添加…...

01DSP学习-了解DSP外设-以逆变器控制为例

(由于是回忆自己简单的DSP学习过程&#xff0c;所以博客看起来有些没有章法&#xff0c;请见谅~) 上一篇博客介绍了学习DSP需要的软件和硬件准备&#xff0c;以及一个DSP的工程包含了哪些东西。我的学习方法是目的导向&#xff0c;即我需要用什么我就学什么&#xff0c;并没有…...

【ArcGIS Pro实操第三期】多模式道路网构建(Multi-model road network construction)原理及实操案例

ArcGIS Pro实操第三期&#xff1a;多模式道路网构建原理及实操案例 1 概述1.1 原理 2 GIS实操2.1 新建文件并导入数据2.2 创建网络数据集2.3 设置连接策略&#xff08;Setting up connectivity policies&#xff09;2.4 添加成本&#xff08;Adding cost attributes&#xff09…...

深度学习基础及技巧

机器学习中的监督学习 监督学习是通过对数据进行分析&#xff0c;找到数据的表达模型&#xff0c;对新输入的数据套用该模型做决策 主要分为训练和预测两个阶段 训练阶段&#xff1a;根据原始数据进行特征提取&#xff0c;然后使用决策树、随机森林等模型算法分析数据之间的特…...

Unity 外描边简单实现(Shader Graph)

1&#xff1a;原理 将物体的模型空间的位置&#xff08;也就是顶点数据&#xff09;放大&#xff0c;作为一个单独的渲染通道单独渲染&#xff0c;这时候模型是已经发大过的&#xff0c;要想看到外描边的效果&#xff0c;需要将正面显示的东西给去掉&#xff0c;显示背面渲染的…...

text2sql方法:NatSQL和DIN-SQL

NatSQL NatSQL出自2021年9月的论文《Natural SQL: Making SQL Easier to Infer from Natural Language Specifications》(github)&#xff0c;它是一种SQL 中间表征(SQL intermediate representation(IR))方法。 NatSQL作者认为Text2SQL的关键挑战是自然语言描述和其对应的SQ…...

【新闻转载】Storm-0501:勒索软件攻击扩展到混合云环境

icrosoft发出警告&#xff0c;勒索软件团伙Storm-0501近期调整了攻击策略&#xff0c;目前正将目标瞄准混合云环境&#xff0c;旨在全面破坏受害者的资产。 该威胁行为者自2021年首次露面&#xff0c;起初作为Sabbath勒索软件行动的分支。随后&#xff0c;他们开始分发来自Hive…...

RabbitMQ 队列之战:Classic 和 Quorum 的性能洞察

RabbitMQ 是一个功能强大且广泛使用的消息代理&#xff0c;它通过处理消息的传输、存储和交付来促进分布式应用程序之间的通信。作为消息代理&#xff0c;RabbitMQ 充当生产者&#xff08;发送消息的应用程序&#xff09;和使用者&#xff08;接收消息的应用程序&#xff09;之…...

盐城市规划建设局网站/百度爱采购优化

公众号关注 「奇妙的 Linux 世界」设为「星标」&#xff0c;每天带你玩转 Linux &#xff01;据BleepingComputer 2月10日消息&#xff0c;Clop 勒索软件组织最近利用 GoAnywhere MFT 安全文件传输工具中的零日漏洞&#xff0c;从 130 多个企业组织中窃取了数据。该安全漏洞被追…...

输入公司名字找不到公司网站/seo免费工具

iphonex 已经上线有一段时间了&#xff0c;作为业界刘海屏幕第一款机型&#xff0c;导致全屏不能正常的全屏显示了&#xff0c;&#xff0c;所以需要对 iphonx 适配&#xff0c;下面就详细说说如何适配 先看一张适配前后的图: iphonex 提供的 meta 头 <meta name"vi…...

微信小程序网站模板/厦门百度seo

对于ASP.NET pages的请求需要有HTTP handler来处理&#xff0c;比如Page的instance。当有一个request来请求某个.aspx页面时&#xff0c;ASP.NET runtime会从ASP.NET thread pool中选一个thread来处理这个request, 并且在这个请求处理完成时释放这个thread。因此&#xff0c;如…...

b2b 网站开发/seo流程

关注公众号&#xff1a; TSparks 名称&#xff1a;尧字节 发送"10年" 不包括引号获取十年架构师文集 发送"23" 获取23种Java设计模式 发送"大咖" 获取大咖视频会议分享 发送"机器" 获取机器学习很棒的入门pdf&#xff0c;讲的非常详…...

上海网站建设明细表/廊坊关键词优化报价

前几天在一个大神群里提到ajax优化选项卡功能的方法上,有位低调的大神默默得打出:了解一下pjax,好奇心的驱使下,我具体查了一下pjax,不一般啊,ax结合pushState和ajax技术&#xff0c; 不需要重新加载整个页面就能从服务器加载Html到你当前页面&#xff0c;这个ajax请求会有永久…...

免费商标图案设计logo/百度seo公司哪家强一点

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼解N元一次方程从文件读入整数 N, 然后读入N*( N1)矩阵&#xff0c;得到解并输出到文件中。int main(){int ch;printf("\n");printf(" Gaussian Matrix Cal \n");printf("\n");printf("Choose:…...