Glide系列--如何监听页面的生命周期

Glide图片加载库

Glide是一个在Android平台上广受欢迎的图片加载库,它专注于快速高效地加载图片,并提供了许多强大的功能和特性。Glide被设计用于处理图片加载过程中的复杂性,包括异步加载、缓存管理、图片变换和资源重用等问题。

主要特点和功能包括:

- 快速高效的图片加载 Glide使用了高效的图片解码和缓存策略,能够快速加载图片并提供流畅的用户体验。
- 自动内存和磁盘缓存 Glide自动管理图片的内存和磁盘缓存,避免了频繁的网络请求和图片解码,提高了图片加载的性能。
- 生命周期感知 Glide能够与Activity和Fragment的生命周期进行关联,确保在它们销毁时自动停止图片加载和释放资源,避免了潜在的内存泄漏问题。
- 灵活的图片变换 Glide支持多种图片变换功能,例如裁剪、旋转、模糊、圆角等,可以根据需要在加载图片时进行处理和转换。
- 网络请求集成 Glide集成了网络请求库,能够直接从网络地址加载图片,也支持加载本地、资源和Content Provider中的图片。
- 加载动态图片和视频缩略图 除了静态图片,Glide还支持GIF、WebP等动态图片格式,以及加载视频的缩略图。
- 自适应图片尺寸 Glide可以根据ImageView的尺寸自动调整图片大小,避免加载过大的图片,节省内存和网络资源。
- 请求优先级和优先加载 开发者可以设置请求的优先级和优先加载指定图片,以满足不同场景下的需求。
- 监听和回调 Glide提供了丰富的监听器和回调接口,允许开发者监控图片加载过程和状态,以及处理加载失败或成功后的逻辑。

总体而言,Glide是一个功能强大且易于使用的图片加载库,为Android开发者提供了简化图片加载流程的解决方案,同时通过优化资源管理和加载性能,提供更好的用户体验。

本篇文章主要探讨Glide的生命周期感知功能,首先我们要了解生命周期感知功能的重要性。

生命周期感知

什么是生命周期感知

在Android开发中,"生命周期感知"是指应用或组件能够察觉和响应其所属的ActivityFragment或其他组件的生命周期状态变化。这意味着当一个组件(如ActivityFragment)进入不同的生命周期阶段(例如创建、启动、停止、销毁等),其关联的其他组件能够感知这些变化并做出相应的操作。

生命周期感知的主要目的是优化资源管理和提升用户体验。通过对组件的生命周期进行感知,应用可以在适当的时机释放资源、停止后台任务、取消网络请求等,从而避免内存泄漏、节省设备电量、提高应用响应速度,以及改善用户对应用的整体满意度。

在Android中,ActivityFragment是最常见的具有生命周期的组件。它们的生命周期包括以下阶段:

  1. 创建( Created :组件被创建但尚未可见,此时可以进行一些初始化工作。

  2. 启动( Started :组件已经可见,但尚未获取焦点,可以开始加载数据或准备展示界面。

  3. 恢复( Resumed :组件可见且获取焦点,用户可以与其进行交互,这是最活跃的状态。

  4. 停止( Stopped :组件不可见但仍然存在,此时可以释放一些不必要的资源。

  5. 销毁( Destroyed :组件被销毁,应该释放所有的资源和取消所有的操作。

通过实现生命周期感知,开发者可以注册监听器或回调来获取组件生命周期变化的通知,并在合适的时机执行相关的操作。Glide图片加载库就是一个很好的例子,它通过监听ActivityFragment的生命周期,自动停止图片加载和释放资源,确保在资源不再需要时能够及时回收,避免内存泄漏和资源浪费。

生命周期感知功能的重要性以及在图片加载中的作用

生命周期感知功能在Android开发中扮演着至关重要的角色,尤其在涉及资源管理和用户体验方面。以下是生命周期感知功能的重要性:

  • 避免内存泄漏 :最重要的一点,在Android应用中,资源未被正确释放可能导致内存泄漏。生命周期感知功能允许在适当的时机释放资源,例如在ActivityFragment销毁时停止后台任务、取消网络请求、释放Bitmap等,从而避免因资源未被及时回收而产生内存泄漏。图片加载涉及到大量的内存操作,例如解码图片、缓存图片等 。如果在加载图片时没有进行适当的生命周期管理,可能会导致内存泄漏。通过生命周期感知,图片加载库可以在ActivityFragment被销毁时自动停止图片加载并释放相关资源,避免了因未释放资源而产生的内存泄漏问题。

  • 优化资源管理 :Android设备的资源(如内存和CPU)是有限的,特别是在较旧或低端的设备上。生命周期感知功能使得应用能够根据当前活动组件(如ActivityFragment)的生命周期状态,有针对性地管理和释放资源,确保应用在资源利用方面更加高效。

  • 避免不必要的计算和网络请求:生命周期感知功能可以在用户不再需要某些数据时自动取消相关的计算和网络请求。这样可以减少后台资源的浪费,提高应用整体的效率。图片加载通常需要进行网络请求或者本地IO操作,这些是耗时的任务。通过生命周期感知,图片加载库可以在后台执行图片加载任务,但在合适的时机及时取消任务,确保在页面销毁时不会加载无用的图片,提高应用的性能和效率。

  • 优化页面回退和导航:对于涉及页面回退和导航的应用场景,生命周期感知功能可以确保在页面不再可见或处于后台时,及时释放相关页面的资源,以避免资源冗余和浪费。

Glide如何实现生命周期感知

在Glide图片加载库中,通过将RequestManagerActivityFragment的生命周期关联起来,可以实现生命周期感知的图片加载操作。这种关联确保在ActivityFragment的生命周期状态变化时,自动停止图片加载并释放相关资源,从而避免内存泄漏和不必要的资源消耗。

要实现RequestManagerActivityFragment的生命周期关联,可以采用如下方式:

  1. 与Activity关联:

在Activity中使用Glide时,通常在onCreate()方法中创建一个RequestManager对象,并将其与Activity进行关联。这样,在Activity生命周期的不同阶段,Glide会自动暂停或恢复图片加载操作。

kotlin 复制代码
class MyActivity : AppCompatActivity() {
    private lateinit var glide: RequestManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 创建Glide的RequestManager并与Activity关联
        glide = Glide.with(this)
        setContentView(R.layout.activity_my)
        // 加载图片等操作可以使用glide对象
        glide.load("https://example.com/image.jpg").into(imageView)
    }

    // 其他Activity生命周期方法
    // ...
}
   
  1. 与Fragment关联:

Fragment中使用Glide时,通常在onCreateView()方法中创建一个RequestManager对象,并将其与Fragment关联。与Activity类似,这样Glide会根据Fragment的生命周期自动管理图片加载操作。

kotlin 复制代码
class MyFragment : Fragment() {
    private lateinit var glide: RequestManager

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_my, container, false)
        // 创建Glide的RequestManager并与Fragment关联
        glide = Glide.with(this)
        // 加载图片等操作可以使用glide对象
        glide.load("https://example.com/image.jpg").into(imageView)
        return view
    }

    // 其他Fragment生命周期方法
    // ...
}

通过以上的方式,Glide会在ActivityFragment的生命周期中智能地暂停或恢复图片加载操作,从而有效地管理资源,避免不必要的资源浪费和内存泄漏。这种生命周期感知的图片加载方式是优化图片加载的重要手段,特别适用于需要加载大量图片或频繁切换页面的场景。

理解RequestManager的概念

理解RequestManager的概念对于使用Glide图片加载库至关重要。在Glide中,RequestManager是一个负责管理图片加载请求的关键组件。它充当了图片加载请求的调度者和管理者,负责创建、处理和停止图片加载请求,并与ActivityFragment的生命周期进行关联,从而实现生命周期感知的图片加载。

要理解RequestManager的概念,可以将其比作一个加载图片请求的"控制中心",类似于一个管理者,可以向下委托具体的图片加载任务,向上感知和响应ActivityFragment的生命周期变化。

主要特点和功能:

  1. 创建和初始化: 在使用Glide加载图片之前,需要先创建一个RequestManager对象。可以通过Glide.with()方法传入ContextActivityFragment来获取相应的RequestManager实例。

  2. 加载图片: 通过RequestManager对象,可以调用load()方法加载指定的图片资源。load()方法支持各种类型的资源加载,包括网络图片、本地图片、资源文件、Uri等。

  3. 图片变换和加载设置: RequestManager还提供了一系列方法,用于设置图片加载时的各种参数和选项,如图片变换、占位符、错误图片、缩略图、优先级等。

  4. 生命周期感知: RequestManagerActivityFragment的生命周期关联,可以根据它们的生命周期状态自动停止或恢复图片加载请求,以优化资源管理和提升用户体验。

  5. 清除资源: 在合适的时机,可以调用clear()方法清除RequestManager中的所有图片加载请求和资源,释放相关资源。

总的来说,RequestManagerGlide图片加载库中的一个关键组件,它在整个图片加载过程中起着重要的调度和管理作用。通过与ActivityFragment的生命周期关联,RequestManager实现了生命周期感知的图片加载功能,确保在适当的时机停止加载和释放资源,从而优化图片加载的性能和资源管理。

RequestManager的创建

Glide中,RequestManager是一个负责管理图片加载请求的关键组件。它充当了图片加载请求的调度者和管理者,负责创建、处理和停止图片加载请求,并与ActivityFragment的生命周期进行关联,从而实现生命周期感知的图片加载。

通常我们在Activity或者Fragment中调用,Glide.with(this),即可完成Glide的初始化,而我们的RequestManager 也是在这个过程中完成创建,因此,我们来看看with函数中做了什么:

less 复制代码
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
  return getRetriever(activity).get(activity);
}

@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
  return getRetriever(fragment.getContext()).get(fragment);
}

@NonNull
public static RequestManager with(@NonNull Context context) {
  return getRetriever(context).get(context);
}

Glide提供了多个静态方法with,实际上,区别只在于入参的不同,而返回值都是RequestManager实例,常用的主要是上面的第一和第二个,入参分别对应FragmentActivity activity / Fragment fragment

不论是哪个静态方法,实现上基本一致,都是通过调用getRetriever方法获取到指定的RequestManagerRetriever,在通过RequestManagerRetriever获取到RequestManager,所以,这里的RequestManagerRetriever 是什么呢?

简单来说 ,RequestManagerRetrieverRequestManager的创建和管理类。它内部维护了一个RequestManager缓存,根据传入的ContextActivityFragment,以及请求类型(通常为ActivityFragment)来查找或创建相应的RequestManager实例。每个应用通常只有一个全局的RequestManagerRetriever对象,用于管理所有的RequestManager实例

在获取到RequestManagerRetriever后,调用RequestManagerRetriever.get方法,获取指定的RequestManager (下文以Fragment为例)

less 复制代码
@NonNull
public RequestManager get(@NonNull Fragment fragment) {
  Preconditions.checkNotNull(
      fragment.getContext(),
      "You cannot start a load on a fragment before it is attached or after it is destroyed");
  if (Util.isOnBackgroundThread()) {
    return get(fragment.getContext().getApplicationContext());
  }
  // In some unusual cases, it's possible to have a Fragment not hosted by an activity. There's
  // not all that much we can do here. Most apps will be started with a standard activity. If
  // we manage not to register the first frame waiter for a while, the consequences are not
  // catastrophic, we'll just use some extra memory.
  if (fragment.getActivity() != null) {
    frameWaiter.registerSelf(fragment.getActivity());
  }
  FragmentManager fm = fragment.getChildFragmentManager();
  Context context = fragment.getContext();
  Glide glide = Glide.get(context.getApplicationContext());
  return lifecycleRequestManagerRetriever.getOrCreate(
      context, glide, fragment.getLifecycle(), fm, fragment.isVisible());
}

get方法完成了以下几件事:

  1. 检查当前的Fragment是否已经attach,或者是否处于destroyed状态;

  2. 判断当前线程是否是后台线程,如果是的话,则获取applicationContext对应的RequestManager,这样做的原因是:在后台线程调用get()方法时,使用fragment.getContext()获取Context是不安全的,因为在**后台线程访问****Context**可能会导致内存泄漏或其他异常

  3. 调用frameWaiter.registerSelf(fragment.getActivity()),此处没理解它的作用;

  4. 获取当前FragmentchildFragmentManager/ fragment所在context(也就是activity)/ 单例的Glide实例

  5. 调用lifecycleRequestManagerRetriever.getOrCreate 完成RequestManager的获取。

lifecycleRequestManagerRetriever.getOrCreate

less 复制代码
RequestManager getOrCreate(
    Context context,
    Glide glide,
    final Lifecycle lifecycle,
    FragmentManager childFragmentManager,
    boolean isParentVisible) {
  Util.assertMainThread();
  RequestManager result = getOnly(lifecycle);
  if (result == null) {
    LifecycleLifecycle glideLifecycle = new LifecycleLifecycle(lifecycle);
    result =
        factory.build(
            glide,
            glideLifecycle,
            new SupportRequestManagerTreeNode(childFragmentManager),
            context);
    lifecycleToRequestManager.put(lifecycle, result);
    glideLifecycle.addListener(
        new LifecycleListener() {
          @Override
          public void onStart() {}

          @Override
          public void onStop() {}

          @Override
          public void onDestroy() {
            lifecycleToRequestManager.remove(lifecycle);
          }
        });
    // This is a bit of hack, we're going to start the RequestManager, but not the
    // corresponding Lifecycle. It's safe to start the RequestManager, but starting the
    // Lifecycle might trigger memory leaks. See b/154405040
    if (isParentVisible) {
      result.onStart();
    }
  }
  return result;
}

getOrCreate方法中干了哪些事呢?

  1. 如果根据fragmentlifecycle获取不到RequestManager实例,则需要新建RequestManager实例,这里也说明RequestManager存在简单的缓存机制;
  2. 当缓存中不存在相应的RequestManager时,新建LifecycleLifecycle对象glideLifeCycle,该对象实现了Lifecycle 接口的相关方法,接着利用工厂模式,通过RequestManagerFactory新建一个RequestManager
less 复制代码
private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
    @NonNull
    public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle, @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
        return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
    }
};
  1. 在新建RequestManager 实例完成后,将fragment.getLifeCycle作为key, 新建的RequestManager 实例为value放入Map缓存;
  2. glideLifeCycle添加生命周期监听,在onDestroy的时侯,将Map中的缓存移除;
  3. Fragment可见时,调用RequestManageronStart方法,在onStart()方法中,首先会调用requestTracker.resumeRequests()方法,该方法会启动图片加载请求,另外调用targetTracker.onStart(),通知targetTracker,当前组件的生命周期已经变为STARTED,因此可以对之前暂停的Target进行恢复加载操作。

targetTrackerRequestManager内部的一个TargetTracker对象,负责管理当前RequestManager中所有图片加载的Target(通常是ImageView或自定义的Target实现)

RequestManager类的简要分析

构造函数

首先让我们分析一下RequestManager的构造函数:

less 复制代码
public RequestManager(
      @NonNull Glide glide,
      @NonNull Lifecycle lifecycle,
      @NonNull RequestManagerTreeNode treeNode,
      @NonNull Context context) {
    this(
        glide,
        lifecycle,
        treeNode,
        new RequestTracker(),
        glide.getConnectivityMonitorFactory(),
        context);
  }

该构造函数接受以下参数:

  1. glide:Glide的实例,是全局的Glide单例,用于管理图片加载请求和资源等。

  2. lifecycle:表示组件(通常是Activity或Fragment)的生命周期状态,用于实现生命周期感知的图片加载。

  3. treeNode:表示一个可选的RequestManager树结构节点,用于组织和管理RequestManager之间的关系。

  4. context:组件的Context,通常是Activity或Fragment的Context。

在构造函数中,它会调用另一个私有的构造函数来完成RequestManager的初始化。

ini 复制代码
private RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    this.glide = glide;
    this.lifecycle = lifecycle;
    this.treeNode = treeNode;
    this.requestTracker = requestTracker;

    connectivityMonitor =
        factory.build(
            context.getApplicationContext(),
            new RequestManagerConnectivityListener(requestTracker));
    // 监听组件的生命周期,根据生命周期状态自动处理图片加载请求
    lifecycle.addListener(this);
  }

在私有构造函数中,它完成了以下操作:

  1. 将传入的参数赋值给类的成员变量。
  2. 通过ConnectivityMonitorFactory创建一个connectivityMonitor,用于监听网络连接状态,以便在适当的时候暂停或恢复图片加载请求。
  3. 通过lifecycle.addListener(this)将当前RequestManager实例注册为生命周期监听器,以便在组件的生命周期变化时触发相应的回调方法。

通过调用lifecycle.addListener(this),RequestManager实现了生命周期感知,并能够根据组件的生命周期状态自动管理图片加载请求,从而优化资源管理和图片加载的性能。

总结:RequestManager的构造函数用于创建RequestManager实例并初始化其成员变量。通过传入Glide实例、生命周期对象和Context等参数,RequestManager能够与Glide和组件的生命周期关联起来,实现生命周期感知的图片加载和资源管理。

成员变量

在Glide的RequestManager类中,有多个成员变量,这些成员变量在图片加载的整个过程中起到重要作用。它们与Glide、组件的生命周期、图片加载请求跟踪和网络连接状态监视器等相互配合,实现了生命周期感知的图片加载和资源管理,以优化图片加载的性能和用户体验。

重要的成员变量 作用
glideGlide的实例 glide变量是全局的Glide单例对象,它用于管理图片加载请求和资源等。通过这个成员变量,RequestManager可以与Glide进行交互,进行图片加载的配置和管理。
lifecycle:组件的生命周期对象。 lifecycle变量用于实现生命周期感知的图片加载。通过与组件的生命周期关联,Glide能够在适当的生命周期状态下自动暂停图片加载请求和释放相关资源,优化图片加载的性能和资源管理。
treeNode :可选的RequestManager树结构节点 treeNode变量通常用于组织和管理RequestManager之间的关系。在某些情况下,例如使用RequestManagerFragmentRequestManagerChildFragment来实现生命周期感知的图片加载,treeNode变量可以用于构建树结构来管理RequestManager的关联。
requestTracker:图片加载请求的跟踪器 requestTracker变量用于跟踪所有图片加载请求的状态,包括正在加载中、已完成、已取消等。通过requestTrackerRequestManager可以管理所有的图片加载请求,并在适当的时机取消请求或释放相关资源。
connectivityMonitor:网络连接状态的监视器 connectivityMonitor变量用于监听网络连接状态,以便在网络连接恢复时恢复图片加载请求。通过这个监视器,Glide可以在网络连接状态变化时适时恢复图片加载请求,提高图片加载的效率和用户体验。

RequestManager在不同生命周期的处理

RequestManager在不同生命周期状态下会根据组件的生命周期变化执行不同的操作。它能够根据组件的生命周期状态来管理图片加载请求和资源,优化图片加载的性能和资源管理。通过生命周期感知的机制,Glide能够在适当的时机自动处理图片加载请求,避免不必要的资源浪费和内存泄漏。

RequestManager在不同生命周期状态下会根据组件(通常是Activity或Fragment)的生命周期变化执行不同的操作。下面是RequestManager在不同生命周期状态下可能会执行的一些操作:

  1. onStart()

    1. 启动网络连接监听 :在onStart()方法中,RequestManager会启动网络连接监听器(如果已注册)。这样,当网络连接恢复时,Glide能够自动恢复之前因网络断开而暂停的图片加载请求,提高图片加载的效率。

    2. 恢复图片加载请求RequestManager会调用requestTracker.resumeRequests()方法,恢复之前因暂停而被停止的图片加载请求。当组件的生命周期状态从STOPPED切换到STARTED时,会触发onStart()方法,从而实现对之前暂停的图片加载请求的恢复。

  2. onStop()

    1. 停止图片加载请求 :在onStop()方法中,RequestManager会调用requestTracker.pauseRequests()方法,暂停所有图片加载请求。当组件的生命周期状态变为STOPPED时,RequestManager会暂停所有图片加载请求,避免在组件不可见时继续加载图片,节省资源和带宽。
  3. onDestroy()

    1. 取消图片加载请求 :在onDestroy()方法中,RequestManager会调用requestTracker.clearRequests()方法,取消所有未完成的图片加载请求。这样,可以避免在组件被销毁时仍然加载图片,避免资源浪费和内存泄漏。

总结

  • Glide是一个强大的图片加载库,其中重要的一方面就是实现了页面生命周期的监听,从而实现了生命周期感知的图片加载和资源管理,优化图片加载的性能和用户体验
  • 生命周期感知的重要作用主要包括避免内存泄漏/优化资源管理/避免不必要的计算和网络请求等;
  • Glide中主要通过RequestManager实现与Fragment/Activity等的关联,监听其页面的生命周期,并通过RequestManagerRetriever 进行RequestManager实例的管理
相关推荐
apihz13 分钟前
通用图片搜索-搜狗源免费API接口使用指南
android·java·python·php·音视频
你过来啊你1 小时前
Android开发中ARouter使用和原理详解
android
apihz2 小时前
腾讯云轻量服务器创建快照免费API接口教程
android·服务器·数据库·python·网络协议·tcp/ip·腾讯云
Kiri霧3 小时前
Noting
android·开发语言·kotlin
东风西巷9 小时前
NealFun安卓版:创意无限,娱乐至上
android·人工智能·智能手机·娱乐·软件需求
小李飞飞砖14 小时前
Sophix、Tinker 和 Robust 三大主流 Android 热修复框架的详细对比
android
感觉不怎么会15 小时前
Android 12 - 部分相机横屏显示方案
android
人生游戏牛马NPC1号17 小时前
学习 Flutter (一)
android·学习·flutter
fundroid18 小时前
Swift 进军 Android,Kotlin 该如何应对?
android·ios
前端世界18 小时前
鸿蒙系统安全机制全解:安全启动 + 沙箱 + 动态权限实战落地指南
android·安全·harmonyos