Glide生命周期管理

1.Glide的简介
Glide,一个被google所推荐的图片加载库,作者是bumptech。这个库被广泛运用在google的开源项目中,包括2014年的google I/O大会上发布的官方app。
2.Glide生命周期的绑定
Glide生命周期绑定是从入口单例类Glide开始的,通过with()多个重载方法来实现对生命周期的绑定工作。大体有五个入口分别为Context、Activity、Fragment、FragmentActivity、View。

//传入一个Context
  public static RequestManager with(@NonNull Context context)
  //传入一个activity
 public static RequestManager with(@NonNull Activity activity)
  //传入一个FragmentActivity
  public static RequestManager with(@NonNull FragmentActivity activity)
  //传入一个Fragment
  public static RequestManager with(@NonNull Fragment fragment)
  //传入一个View
  public static RequestManager with(@NonNull View view)

传入context和view都会对其进行类别判断,如果不属于Activity、Fragment和FragmentActivity 则生命周期与应用同步,无需处理。

//传入参数为context时
public RequestManager get(Context context) {
    if (context == null) {
      throw new IllegalArgumentException("You cannot start a load on a null Context");
    } else if (Util.isOnMainThread() && !(context instanceof Application)) {
      if (context instanceof FragmentActivity) {
       //判断参数类型是不是FragmentActivity
        return get((FragmentActivity) context);
      } else if (context instanceof Activity) {
       //判断参数类型是不是FragmentActivity
        return get((Activity) context);
      } else if (context instanceof ContextWrapper) {
      //判断context类型是不是ContextWrapper
        return get(((ContextWrapper) context).getBaseContext());
      }
    }
   //context类型属于ApplicationContext
    return getApplicationManager(context);
  }
//传入参数是view时
public RequestManager get(View view) {
    if (Util.isOnBackgroundThread()) {
      return get(view.getContext().getApplicationContext());
    }
    Preconditions.checkNotNull(view);
    Preconditions.checkNotNull(view.getContext(),
        "Unable to obtain a request manager for a view without a Context");
    Activity activity = findActivity(view.getContext());
    // The view might be somewhere else, like a service.
    if (activity == null) {
      return get(view.getContext().getApplicationContext());
    }
    // Support Fragments.
    // Although the user might have non-support Fragments attached to FragmentActivity, searching
    // for non-support Fragments is so expensive pre O and that should be rare enough that we
    // prefer to just fall back to the Activity directly.
    if (activity instanceof FragmentActivity) {
      Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
      return fragment != null ? get(fragment) : get(activity);
    }
    // Standard Fragments.
    android.app.Fragment fragment = findFragment(view, activity);
    if (fragment == null) {
      return get(activity);
    }
    return get(fragment);
  }

但传入的context不属于Activity、Fragment和FragmentActivity 会调用getApplicationManager方法,这里就直接创建一个ApplicationLifecycle来管理生命周期,但ApplicationLifecycle并不受控制,所以就无法对Glide生命周期进行管理。

 private RequestManager getApplicationManager(@NonNull Context context) {
    // Either an application context or we're on a background thread.
    if (applicationManager == null) {
      synchronized (this) {
        if (applicationManager == null) {
          Glide glide = Glide.get(context.getApplicationContext());
          applicationManager =
              factory.build(
                  glide,
                  new ApplicationLifecycle(),
                  new EmptyRequestManagerTreeNode(),
                  context.getApplicationContext());
        }
      }
    }
    return applicationManager;
  }

当传入参数类型为Activity时,代码实现如下。

public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
  }
  public RequestManager get(@NonNull Activity activity) {
    //如果在子线程,获取applicationContext传入get方法中,最后调用getApplicationManager方法   代表不对Glide生命周期进行管理
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      //拿到FragmentManager对象
      android.app.FragmentManager fm = activity.getFragmentManager();
      //创建fragment对象,并返回一个RequestManager 对象
      return fragmentGet(
          activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

如果当前是在子线程,获取applicationContext传入get方法中,最后调用getApplicationManager方法 ,代表不需要对Glide生命周期进行管理,否则将通过fragmentGet方法创建一个fragment

private RequestManager fragmentGet(@NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    //创建一个fragment对象
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
   
      Glide glide = Glide.get(context);
      //创建一个RequestManager对象
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

在fragmentGet方法中,通过getRequestManagerFragment来获得一个Fragment对象。然后拿到该Fragment对应的RequestManager 对象,如果该对象为null则创建一个RequestManager对象并将fragment中的ActivityFragmentLifecycle对象传递给RequestManager。先来看getRequestManagerFragment方法的实现。

private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    //查找tag为FRAGMENT_TAG的fragment
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
      //从HashMap中取出fm
      current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
        //创建fragment对象
        current = new RequestManagerFragment();
        //当fragment嵌套fragment时才会使用,否则parentHint是null
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
          //开始执行请求
          current.getGlideLifecycle().onStart();
        }
        //将fm添加到HashMap中,防止fragment的重复创建
        pendingRequestManagerFragments.put(fm, current);
        //添加fragment
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        //从HashMap集合从移除fm
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

从fm中去查找tag为FRAGMENT_TAG的fragment是否存在,如果不存在就从pendingRequestManagerFragments这个HashMap中去取,如果没有就创建一个fragment,接着将刚刚生成的Fragment加入事物管理器中,但是紧接着又调用handel发送了一条消息,我们进入handleMessage()方法中,可以发现它将刚刚加入HashMap的Fragment又删除了。这里的pendingRequestManagerFragments主要是防止fragment重复创建,因为每个activity必须对应一个唯一的fragment。add后又要马上发一个消息remove掉是为了在前面阻止重复new和add的操作后,就把这个缓存删掉,可以避免内存泄漏和内存压力。
举个例子来分析一下这个过程。

Glide.with(context).load(url).into(image1);
Glide.with(context).load(url).into(image2);

我们看上面的两行代码,在同一个Activity中分别为两个ImageView加载图片。
当第一行代码运行到getRequestManagerFragment()方法时,由于之前没有RequestManagerFragment实例,这个时候会生成一个新的RequestManagerFragment实例,并保存在HashMap中,生成新的RequestManagerFragment实例时,就会发Fragment于Activity的绑定,Handler会发送消息来进行绑定,假设这个消息为m1,紧接着在getRequestManagerFragment()方法中,就会使用Handler来发送从HashMap中删除保存的RequestManagerFragment实例对象的消息,假设这个消息为m2。
在Handler处理消息时,如果在m1与m2消息之前,Handler的消息队列中还存在其他的消息,此时m1与m2还没有得到处理,就是此时还没有进行Fragment与Activity的绑定。第二行Glide.with(context).load(url).into(image2);代码已经进行到了getRequestManagerFragment()方法了,如果此时我们不将Fragment存入HashMap中,就会重新生成一个RequestManagerFragment,这是Glide所不允许的,每一个Activity或者Fragment在使用Glide时,只能有一个所依附的虚拟的Fragment。所以将之前所生成的RequestManagerFragment存储到HashMap中,这样就不会重复生成RequestManagerFragment,等到RequestManagerFragment与Activity绑定完成后,也就是消息m1处理完成后,再将RequestManagerFragment从HashMap中销毁。
接下来看一下这个fragment的实现RequestManagerFragment。

public class RequestManagerFragment extends Fragment {
  private final ActivityFragmentLifecycle lifecycle;
  public SupportRequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
  }
  public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
    this.lifecycle = lifecycle;
  }
  ...
  @NonNull
  ActivityFragmentLifecycle getGlideLifecycle() {
    return 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();
  }
  ...
}

可以看到在RequestManagerFragment的构成函数里会生成ActivityFragmentLifecycle对象。ActivityFragmentLifecycle类是生命周期回调的管理类,它实现了LifeCycle接口,会将LifecycleListener的接口加入到ActivityFragmentLifecycle类中的Set集合中,当RequestManagerFragment的生命周期的方法触发时,会调用ActivityFragmentLifeCycle的相应方法。再回到fragmentGet方法,fragment创建成功后,在创建RequestManager时会传入fragment中的ActivityFragmentLifecycle,再来看RequestManager的实现。

public class RequestManager implements LifecycleListener,
    ModelTypes<RequestBuilder<Drawable>> {
  private final Runnable addSelfToLifecycle = new Runnable() {
    @Override
    public void run() {
      lifecycle.addListener(RequestManager.this);
    }
  };
  public RequestManager(
      @NonNull Glide glide, @NonNull Lifecycle lifecycle,
      @NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
    this(
        glide,
        lifecycle,
        treeNode,
        new RequestTracker(),
        glide.getConnectivityMonitorFactory(),
        context);
  }

  // Our usage is safe here.
  @SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
  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;
    ...
    if (Util.isOnBackgroundThread()) {
      //当在子线程时通过Handler将当前对象注册到ActivityFragmentLifecycle
      mainHandler.post(addSelfToLifecycle);
    } else {
      //将当前对象注册到ActivityFragmentLifecycle
      lifecycle.addListener(this);
    }
    //网络变化监听
    lifecycle.addListener(connectivityMonitor);
    ...
  }
  //开始加载
  @Override
  public synchronized void onStart() {
    resumeRequests();
    //如果有动画则开始动画
    targetTracker.onStart();
  }
  //停止加载
  @Override
  public synchronized void onStop() {
    pauseRequests();
    //如果有动画则动画停止
    targetTracker.onStop();
  }
  //销毁
  @Override
  public synchronized void onDestroy() {
    //如果有动画则动画结束并销毁
    targetTracker.onDestroy();
    ...
  }
  //开始请求数据
  synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }
 ...
}

可以看见在RequestManager的构造函数将RequestManager注册到ActivityFragmentLifecycle中,再来看看ActivityFragmentLifecycle的实现。

class ActivityFragmentLifecycle implements Lifecycle {
  private final Set<LifecycleListener> lifecycleListeners =
      Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
  private boolean isStarted;
  private boolean isDestroyed;
  @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);
  }
  //每个RequestManager对应一个LifecycleListener 
  void onStart() {
    isStarted = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart();
    }
  }
  //每个RequestManager对应一个LifecycleListener 
  void onStop() {
    isStarted = false;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStop();
    }
  }
  //每个RequestManager对应一个LifecycleListener 
  void onDestroy() {
    isDestroyed = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onDestroy();
    }
  }
}

由于ActivityFragmentLifecycle对象是在fragment中创建并且它的onStart、onStop、onDestory方法与fragment一一对应,这样就将RequestManager的生命周期就与fragment关联起来了,也就与当前activity关联起来 。通过上面的源码可以发现Glide生命周期是通过创造一个不可见的fragment然后把这个fragment和activity进行绑定实现的。
因为with还可能会传入fragment,为了确保fragment所创建的RequestManagerFragment是依附在Activity所创建的RequestManagerFragmen下面的,我们可以看到RequestManagerFragment还有一个rootRequestManagerFragment的成员变量。这个fragment即顶级的Activity所创建的RequestManagerFragment,Glide每创建一个RequestManagerFragment,都会尝试实例化rootRequestManagerFragment,相关代码

public void onAttach(Activity activity) {
    super.onAttach(activity);
    rootRequestManagerFragment = RequestManagerRetriever.get()
            .getRequestManagerFragment(getActivity().getFragmentManager());
    if (rootRequestManagerFragment != this) {
        rootRequestManagerFragment.addChildRequestManagerFragment(this);
    }
}

@Override
public void onDetach() {
    super.onDetach();
    if (rootRequestManagerFragment != null) {
        rootRequestManagerFragment.removeChildRequestManagerFragment(this);
        rootRequestManagerFragment = null;
    }
}

可以看到,不管当前的RequestManagerFragment是通过何种方式创建的,都会在OnAttach时,拿到当前所绑定的Activity的FragmentManager来初始化一个RequestManagerFragment,这个RequestManagerFragment有可能是自身,有可能已经被初始化过了,比如是通过with(Activity activity)的方式初始化的,那么很显然

RequestManagerRetriever.get().getRequestManagerFragment(getActivity().getFragmentManager());

这句代码拿到的会是自己本身,而如果是通过with(Fragment fragment)的形式创建的,rootRequestManagerFragment将指向当前fragment绑定到Activity所绑定的RequestManagerFragment,如果该Activity没有绑定过,那么会开启事务绑定一个RequestManagerFragment。并且如果自己不是rootRequestManagerFragment的话,那么将会把自己保存到rootRequestManagerFragment中的一个集合:

private void addChildRequestManagerFragment(RequestManagerFragment child) {
    childRequestManagerFragments.add(child);
}

简而言之,Glide会为Activity创建一个RequestManagerFragment做为rootFragment,并保存该Activity底下所有Fragment(如果有的话)所创建的RequestManagerFragment。


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

推荐阅读更多精彩内容