Glide4.x 任务与上下文生命周期关联的实现分析

本文深入探讨了Glide4.x如何关联上下文生命周期,分析了其暂停请求、获取生命周期的实现方式,以及`with`方法的作用。通过RequestManager和RequestTracker的交互,展示了Glide在Android应用中的图片加载优化策略,如在上下文暂停时自动暂停请求,恢复时重新启动请求,并在销毁时回收资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明出处:王亟亟的大牛之路

写之前先安利,接下来2 3个月我会花点时间捡起一些安卓的技能,看看这2年没花什么精力投入的安卓变成啥样子了https://github.com/ddwhan0123/Useful-Open-Source-Android


什么是Glide?

Glide是一个快速高效的Android图片加载库,注重于平滑的滚动。Glide提供了易用的API,高性能、可扩展的图片解码管道(decode pipeline),以及自动的资源池技术。
Glide 支持拉取,解码和展示视频快照,图片,和GIF动画。Glide的Api是如此的灵活,开发者甚至可以插入和替换成自己喜爱的任何网络栈。默认情况下,Glide使用的是一个定制化的基于HttpUrlConnection的栈,但同时也提供了与Google Volley和Square OkHttp快速集成的工具库。
虽然Glide 的主要目标是让任何形式的图片列表的滚动尽可能地变得更快、更平滑,但实际上,Glide几乎能满足你对远程图片的拉取/缩放/显示的一切需求。


本篇研究的内容和目的

  • Glide如何暂停请求
  • Glide如何获取生命周期
  • 以上二者是如何实现的

入口方法

  Glide.with(this).load(img_url).into(imageView)

简单的一句加载函数

.with() 关联了一个上下文环境的对象

.load()关联了你要加载的资源的路径(load是一个多态的方法,可以是url,字符串地址,文件等等等方式)

.into()是把以上的内容加载到哪个控件里去(into()方法也是,面向的是ViewTarget<a,b>的泛形)


with的做了什么

在这里插入图片描述
所有with方法都返回了一个RequestManager对象
在这里插入图片描述
RequestManager的get方法会根据不同的入参类型去构建RequestManager对象(以下以Activity的场景为例)

  @NonNull
  public RequestManager get(@NonNull Activity activity) {
	  //判断是否在前台,否则调用更大引用周期的上下文对象
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
    	//有效生命周期内才继续初始化流程
      assertNotDestroyed(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
      //传入4个参数上下文对象,activity的FragmentManager实现,空,true(是否前台可见)
      return fragmentGet(
          activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

fragmentGet方法是实质构建RequestManager对象的方法,无论如何不会为空返回

 @Deprecated
  @NonNull
  private RequestManager fragmentGet(@NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // TODO(b/27524013): Factor out this Glide.get() call.
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

RequestManager

我们来看一下这个类的源码,看下他是如何实现的。

public class RequestManager implements LifecycleListener,
    ModelTypes<RequestBuilder<Drawable>> {}

实现了LifecycleListener接口,也就是onDestroy,onStart,onStop几个方法的回调都能拿到,可以在其中实现自己的业务逻辑

  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;
    this.context = context;
	//网络状态的监听
    connectivityMonitor =
        factory.build(
            context.getApplicationContext(),
            new RequestManagerConnectivityListener(requestTracker));
    //不同的上下文生命周期使用不同的监听        
    if (Util.isOnBackgroundThread()) {
      mainHandler.post(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);

    defaultRequestListeners =
        new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
    setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
	//glide整个的请求管理托付于这个类
    glide.registerRequestManager(this);
  }

构造函数获取了Glide和之前由最外层context初始化的RequestManagerFragment的一些属性,当然初始化的时候还有一些静态内部的常量,构建了RequestOptions的一些属性

接下来看一下这个类实现了哪些功能(只解释跟我们主题相关的)

判断当前上下文对象的生命周期是否处于暂停状态

  public synchronized boolean isPaused() {
    return requestTracker.isPaused();
  }

暂停正在执行中的请求

 public synchronized void pauseRequests() {
    requestTracker.pauseRequests();
  }

暂停请求,且清楚已完成的加载内容

public synchronized void pauseAllRequests() {
    requestTracker.pauseAllRequests();
  }

恢复所有未完成的请求

  public synchronized void resumeRequests() {
    requestTracker.resumeRequests();
  }
 @Override
  public synchronized void onStart() {
    //恢复请求
    resumeRequests();
    targetTracker.onStart();
  }
  @Override
  public synchronized void onStop() {
    //暂停请求
    pauseRequests();
    targetTracker.onStop();
  }

回收资源,移除监听

  @Override
  public synchronized void onDestroy() {
    targetTracker.onDestroy();
    for (Target<?> target : targetTracker.getAll()) {
      clear(target);
    }
    targetTracker.clear();
    requestTracker.clearRequests();
    lifecycle.removeListener(this);
    lifecycle.removeListener(connectivityMonitor);
    mainHandler.removeCallbacks(addSelfToLifecycle);
    glide.unregisterRequestManager(this);
  }

这里看到RequestTracker其实是RequestManager实现的代理。我们找了3层终于了具体实现生命周期回调,和调用终止/恢复请求的地方。

RequestTracker

没有带参的构造函数,内部维护了请求队列

public class RequestTracker {
  private static final String TAG = "RequestTracker";
   private final Set<Request> requests =
      Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
       private final List<Request> pendingRequests = new ArrayList<>();
  private boolean isPaused;
  }
在调用into()方法后会被执行,Request是个接口,实现了请求,取消,暂停等功能方法
  public void runRequest(@NonNull Request request) {
    requests.add(request);
    if (!isPaused) {
      request.begin();
    } else {
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
      pendingRequests.add(request);
    }
  }

暂停请求,并回收

 public boolean clearRemoveAndRecycle(@Nullable Request request) {
    return clearRemoveAndMaybeRecycle(request, /*isSafeToRecycle=*/ true);
  }

在初次启动请求时会设置为false,是否暂停请求的控制flag

 public boolean isPaused() {
    return isPaused;
  }

在容器生命周期onStop()回调中恢复请求暂停请求

  public void pauseRequests() {
    isPaused = true;
    for (Request request : Util.getSnapshot(requests)) {
      if (request.isRunning()) {
        request.clear();
        pendingRequests.add(request);
      }
    }
  }

在容器生命周期onStart()回调中恢复请求

  public void resumeRequests() {
    isPaused = false;
    for (Request request : Util.getSnapshot(requests)) {
      if (!request.isComplete() && !request.isRunning()) {
        request.begin();
      }
    }
    pendingRequests.clear();
  }

清除请求并回收,在上下文生命周期的onDestroy()处调用

  public void clearRequests() {
    for (Request request : Util.getSnapshot(requests)) {
      clearRemoveAndMaybeRecycle(request, /*isSafeToRecycle=*/ false);
    }
    pendingRequests.clear();
  }

在网络监听到连接的状态下,重新请求,包括失败的/暂停的/进行中的

 public void restartRequests() {
    for (Request request : Util.getSnapshot(requests)) {
      if (!request.isComplete() && !request.isCleared()) {
        request.clear();
        if (!isPaused) {
          request.begin();
        } else {
          pendingRequests.add(request);
        }
      }
    }
  }

总结

第一步:with方法挂载上下文对象用以获取他的生命周期,并初始化RequestManager对象。
第二部:RequestManager对象初始化了RequestOptions,以及实现一系列生命周期与业务逻辑相关联的方法,并且实现了.load()方法,把资源方面的实现与上下文相关业务实现分离。
第三部:RequestManager用自己的代理实现RequestTracker类维护了未完成和完成两个任务队列,通过Request接口分别实行不同的业务方法

简要知识点:
调用into()方法后才会开始执行业务请求
网络状态已经实现监听,业务端不用自己监听后调用clear()
Glide网络监听接口只区分断没断网,不管理网络类型(暂未发现对4g/3g/2g/wifi等场景的特殊处理)

其他

有问题欢迎沟通,但请注明来意
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值