Android Glide源码剖析系列(一)图片加载请求如何感知组件生命周期


Glide源码剖析系列


为什么选择Glide?

  • 多种图片格式的缓存,适用于更多的内容表现形式(如Gif、WebP、缩略图、Video)
  • 生命周期集成(根据Activity或者Fragment的生命周期管理图片加载请求)Glide可以感知调用页面的生命周期,这就是优势
  • 高效处理Bitmap(bitmap的复用和主动回收,减少系统回收压力)
  • 高效的缓存策略,灵活(Picasso只会缓存原始尺寸的图片,Glide缓存的是多种规格),加载速度快且内存开销?。螧itmap格式的不同,使得内存开销是Picasso的一半)

小结:支持图片格式多;Bitmap复用和主动回收;生命周期感应;优秀的缓存策略;加载速度快(Bitmap默认格式RGB565)

Glide简单使用

Glide.with(this)
        .load("https://t7.baidu.com/it/u=3779234486,1094031034&fm=193&f=GIF")
        .into(imageView);

源码分析

我们以Gide.with(activity)方法为切入点开始分析源码

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

只需要一行代码,两步轻松获取RequestManager实例

第一步、getRetriever(activity):获取到RequestManagerRetriever实例

  //1. 单例模式创建Glide实例
  //2. 获取RequestManagerRetriever实例
  @NonNull
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    // Context could be null for other reasons (ie the user passes in null), but in practice it will
    // only occur due to errors with the Fragment lifecycle.
    Preconditions.checkNotNull(
        context,
        "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
            + "returns null (which usually occurs when getActivity() is called before the Fragment "
            + "is attached or after the Fragment is destroyed).");
    return Glide.get(context).getRequestManagerRetriever();  //分两步分析
  }

1.1 使用单例模式获取Glide实例

  public static Glide get(@NonNull Context context) {
    if (glide == null) {
      GeneratedAppGlideModule annotationGeneratedModule =
          getAnnotationGeneratedGlideModules(context.getApplicationContext());
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context, annotationGeneratedModule);
        }
      }
    }
    return glide;
  }

1.2 继续追踪调用链:checkAndInitializeGlide() -> initializeGlide()

  private static void initializeGlide(
      @NonNull Context context,
      @NonNull GlideBuilder builder,
      @Nullable GeneratedAppGlideModule annotationGeneratedModule) {
    ……
    Glide glide = builder.build(applicationContext);  //建造者模式创建Glide实例
    ……
    Glide.glide = glide;
  }

1.3 最终调用GlideBuilder.build()方法构建Glide实例

  @NonNull
  Glide build(@NonNull Context context) {

   //此处省略初始化默认配置信息代码
    ……

    //创建实例并赋值给Glide成员变量requestManagerRetriever 
    //这里传入的requestManagerFactory是用来创建RequestManager的工厂,第2步分析
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory, experiments);

    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptionsFactory,
        defaultTransitionOptions,
        defaultRequestListeners,
        experiments);
  }

获取RequestManagerRetriever小结:

  • RequestManagerRetriever的创建是在Glide的初始化过程中完成的;
  • RequestManagerRetriever构造方法内传入requestManagerFactory,用来创建RequestManager

第二步、get(activity) 创建并返回RequestManager 实例

  @NonNull
  public RequestManager get(@NonNull FragmentActivity activity) {
    if (Util.isOnBackgroundThread()) { 
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      frameWaiter.registerSelf(activity);
      FragmentManager fm = activity.getSupportFragmentManager();
      return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

2.1 如果当前线程不是主线程,直接转到get(activity.getApplicationContext())中执行;否则继续调用supportFragmentGet()方法

  @NonNull
  private RequestManager supportFragmentGet(
      @NonNull Context context,
      @NonNull FragmentManager fm,
      @Nullable Fragment parentHint,
      boolean isParentVisible) {
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // TODO(b/27524013): Factor out this Glide.get() call. (移除此处的Glide.get())
      Glide glide = Glide.get(context);
      //工厂模式创建requestManager,关于factory见分析2.2
      requestManager = factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      if (isParentVisible) {
        requestManager.onStart();
      }
      current.setRequestManager(requestManager);  //requestManager存储到隐藏的Fragment
    }
    return requestManager;
  }

2.2 RequestManagerFactory 初始化过程

#RequestManagerRetriever.java
  //默认RequestManagerFactory 
  private static final RequestManagerFactory DEFAULT_FACTORY =
      new RequestManagerFactory() {
        @NonNull
        @Override
        public RequestManager build(
            @NonNull Glide glide,
            @NonNull Lifecycle lifecycle,
            @NonNull RequestManagerTreeNode requestManagerTreeNode,
            @NonNull Context context) {
          return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
        }
      };

  public RequestManagerRetriever(
      @Nullable RequestManagerFactory factory, GlideExperiments experiments) {
    this.factory = factory != null ? factory : DEFAULT_FACTORY;  //默认使用DEFAULT_FACTORY
    handler = new Handler(Looper.getMainLooper(), this /* Callback */);

    frameWaiter = buildFrameWaiter(experiments);
  }

默认使用DEFAULT_FACTORY来创建RequestManager,见2.1requestManager = factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);

2.3 RequestManager构造方法

#RequestManager.java
  RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    //省略其他代码
    if (Util.isOnBackgroundThread()) {
      Util.postOnUiThread(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);
  }

  private final Runnable addSelfToLifecycle =
      new Runnable() {
        @Override
        public void run() {
          lifecycle.addListener(RequestManager.this);
        }
      };

把当前RequestManager添加到lifecycle,lifecycle是ActivityFragmentLifecycle类型,在SupportRequestManagerFragment 构造方法中创建,后文会介绍SupportRequestManagerFragment类。

重点类总结:

RequestManager implements LifecycleListener
  • 操作和管理Glide加载图片的请求
  • 实现LifecycleListener接口,根据Activity、Fragment生命周期变化和网络状态来控制图片加载流程
  • 由RequestManagerRetriever统一创建和管理,创建时使用工厂模式
RequestManagerRetriever
  • 作用是创建和复用RequestManager:使用RequestManagerRetriever.RequestManagerFactory工厂创建RequestManager,复用SupportRequestManagerFragment 中已有的RequestManager
  • 在Glide初始化时创建
SupportRequestManagerFragment 无视图的Fragment
  • 安全存储RequestManager,由RequestManagerRetriever负责绑定
  • 添加到当前Activity,利用SupportRequestManagerFragment 的生命周期变化来控制图片的加载流程

到目前为止,我们了解了大致的框架结构,接下来正式进入到本文的主题

RequestManager如何感知组件的生命周期

我们知道感知生命周期的手段是添加隐藏的SupportRequestManagerFragment,继续查看RequestManagerRetriever#getSupportRequestManagerFragment源码:

#RequestManagerRetriever.java

  /** Pending adds for SupportRequestManagerFragments. */
  @VisibleForTesting
  //缓存已经添加的隐藏SupportRequestManagerFragment
  final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments = new HashMap<>();

  @NonNull
  private SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
    //1. 检查是否已经添加了隐藏的SupportRequestManagerFragment ,使用HashMap缓存SupportRequestManagerFragment 
    // 2. 查找FragmentManager 中是否有可以复用的SupportRequestManagerFragment 
    //如果都没有找到,创建一个新的SupportRequestManagerFragment,
    //并且添加到pendings列表&&提交到FragmentManager
    SupportRequestManagerFragment current = pendingSupportRequestManagerFragments.get(fm);
    if (current == null) {
      current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
      if (current == null) {
        current = new SupportRequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        pendingSupportRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

现在隐藏的SupportRequestManagerFragment已经添加成功,继续分析SupportRequestManagerFragment.java源码

  private final ActivityFragmentLifecycle lifecycle;

  //构造方法
  public SupportRequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
  }

  @VisibleForTesting
  @SuppressLint("ValidFragment")
  public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
    this.lifecycle = lifecycle;
  }

  ……

  @Override
  public void onStart() {
    super.onStart();
    lifecycle.onStart();
  }

  @Override
  public void onStop() {
    super.onStop();
    lifecycle.onStop();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    lifecycle.onDestroy();
    unregisterFragmentWithRoot();
  }

新建一个ActivityFragmentLifecycle实例赋值给SupportRequestManagerFragment的lifecycle成员变量,查看ActivityFragmentLifecycle类

class ActivityFragmentLifecycle implements Lifecycle {
//储存LifecycleListener的列表
  private final Set<LifecycleListener> lifecycleListeners =
      Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
  private boolean isStarted;
  private boolean isDestroyed;

  /**
   * 向lifecycleListeners列表添加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);
  }

  void onStart() {    //遍历执行onStart
    isStarted = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart();
    }
  }

//与onStart类似
  void onStop() {
    ……
  }
  void onDestroy() {
     ……
  }
}

使用观察者模式,在组件生命周期发生变化的时候回调相应的操作方法。这一切都是框架帮助咱们完成的,在RequestManager构造函数中把自身加入到ActivityFragmentLifecycle的成员变量lifecycleListeners中。

#RequestManager.java
  RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    //省略其他代码
    if (Util.isOnBackgroundThread()) {
      Util.postOnUiThread(addSelfToLifecycle);  //切换到主线程执行
    } else {
      lifecycle.addListener(this);  //添加到ActivityFragmentLifecycle成员变量lifecycleListeners
    }
    lifecycle.addListener(connectivityMonitor);
  }

  private final Runnable addSelfToLifecycle =
      new Runnable() {
        @Override
        public void run() {
          lifecycle.addListener(RequestManager.this);  //添加到ActivityFragmentLifecycle成员变量lifecycleListeners
        }
      };

监听组件生命周期流程汇总:

  1. 创建无试图SupportRequestManagerFragment 绑定到当前Activity;
    SupportRequestManagerFragment 持有RequestManager实例,RequestManager实例由RequestManagerRetriever创建并传递给SupportRequestManagerFragment ;

  2. RequestManager持有ActivityFragmentLifecycle引用,在SupportRequestManagerFragment 构造方法中产生并传递给RequestManager;
    RequestManager在构造函数中把自己加入到ActivityFragmentLifecycle.lifecycleListeners列表

  3. 生命周期同步过程,以Activity调用onStart()为例:

(1)Activity调用onStart()
(2)SupportRequestManagerFragment调用onStart()

  @Override
  public void onStart() {
    super.onStart();
    lifecycle.onStart(); //==ActivityFragmentLifecycle.onStart()
  }

(3)ActivityFragmentLifecycle#onStart()

  void onStart() {
    isStarted = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart(); //==RequestManager.onStart()
    }
  }

(4)RequestManager#onStart()

  @Override
  public synchronized void onStart() {
    resumeRequests();  //启动图片加载请求
    targetTracker.onStart();  //添加到TargetTracker,统一管理targets响应组件生命周期
  }

图片加载时感知组件生命周期全过程END

结语

本文我们以一个图片加载请求为例,大致了解了Glide感知组件生命周期的原理,但是实际项目中必然会有许多图片加载请求同时存在,所以必须要有一个机制来统一管理这些图片请求,这样才能在组件生命周期变化时改变这些请求的状态。

关于图片加载请求如何加入到请求列表?Glide又是如何管理这些请求?下一篇文章继续分析!

Android Glide源码解析系列(二)Glide如何管理图片加载请求

最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,172评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,346评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,788评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,299评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,409评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,467评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,476评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,262评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,699评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,994评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,167评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,499评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,149评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,387评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,028评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,055评论 2 352

推荐阅读更多精彩内容