掌握Glide(2) : 从源码看,Glide是如何关联生命周期的

本文将从源码的角度,分析Glide是如何关联生命周期的。
如无特殊说明,源码版本均指:4.6.1

学习Glide是如何关联生命周期的,核心在于一个知识点:
fragment的生命周期,是与Activity生命周期对应的。

明白并牢记这一点可,以更好的理解本文。

一.生命周期绑定

我们先以继承AppCompatActivity(它的父类是FragmentActivity)为例分析。在第3部分,我们再进行拓展到一般情况。

Glide加载图片最基本的方式如下:

Glide.with(MainActivity.this).load(url).into(mImageView);

Glide生命周期绑定是从入口单例类Glide开始的,通过with()多个重载方法来实现对生命周期的绑定工作。

1. with()方法

这个方法有多个重载,可以传入ContextActivityFragmentView等,但是内部调用方法都是一样的,只是参数有所不同,这里以传入FragmentActivity为例。

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

第4行代码中, getRetriever(activity) ,返回的是 RequestManagerRetriever

第4行代码 整体看,即看 RequestManagerRetriever.class中的get方法:

代码片2  #RequestManagerRetriever.class

@NonNull
  public RequestManager get(@NonNull FragmentActivity activity) {
     
    //如果是在子线程
    if (Util.isOnBackgroundThread()) {
          --->2部分会分析(2A)
      return get(activity.getApplicationContext());    
    } else {
     
      //如果是在主线程
      assertNotDestroyed(activity);
       //获取当前Activity的FragmentManager
      //用于后续将创建的Fragment绑定到activity
      FragmentManager fm = activity.getSupportFragmentManager();
      return supportFragmentGet(activity, fm, null /*parentHint*/);
    }
  }

那我们看一下supportFragmentGet方法:

代码片3   #RequestManagerRetriever.class

 @NonNull
  private RequestManager supportFragmentGet(@NonNull Context context, @NonNull FragmentManager fm,
      @Nullable Fragment parentHint) {
     
     
    //创建无UI的fragment(第2部分分析),并绑定到当前activity
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint); --->分析3A
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
     
      // TODO(b/27524013): Factor out this Glide.get() call.
      Glide glide = Glide.get(context);
      //创建RequestManager,获取fragment的lifecycle,传入requestManager
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

我们看一下3A(代码片3第8行)的SupportRequestManagerFragment 是如何获取的。进入getSupportRequestManagerFragment方法:

代码片4   #RequestManagerRetriever.class

// pendingSupportRequestManagerFragments是一个map集合
 @VisibleForTesting
  final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
      new HashMap<>();

 @NonNull
  SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
     
       //1、由FragmentManager通过tag获取fragment
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
     
      //2、从缓存集合中获取fragment的,map以fragmentManger为key,
      //以fragment为value进行存储
      current = pendingSupportRequestManagerFragments.get(fm);
      if (current == null) {
     
        //3、创建一个fragment实例
        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();  ---(3部分会分析)分析4A
      }
    }
    return current;
  }

小结:

1、创建无UIFragment,并绑定到当前activity
2、通过builder模式创建RequestManager,并且将fragmentlifecycle传入,这样FragmentRequestManager就建立了联系;
3、获取Fragment对象,先根据tag去找,如果没有从内存中查找,pendingSupportRequestManagerFragments是一个存储fragment实例的HashMap,再没有的话就new一个。

2. SupportRequestManagerFragment 类

我们看一下SupportRequestManagerFragment类具体是怎么样的?

代码片5    SupportRequestManagerFragment.class

public class SupportRequestManagerFragment extends Fragment {
     
 
  private final ActivityFragmentLifecycle lifecycle;
   //省略部分代码

  public SupportRequestManagerFragment() {
     
    this(new ActivityFragmentLifecycle());    
  }

  @VisibleForTesting
  @SuppressLint("ValidFragment")
  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的生命周期相关的函数调用lifecycle对象对应的方法,而lifecycle是在SupportRequestManagerFragment构造函数数中创建的:

public SupportRequestManagerFragment() {
     
    this(new ActivityFragmentLifecycle());
}

3. ActivityFragmentLifecycle类

看一下ActivityFragmentLifecycle.class类。

这个类实际是一个生命周期回调的管理类,实现了Lifecycle接口。所有的LifecycleListener会添加到一个集合中,当RequestManagerFragment生命周期方法触发时,会调用ActivityFragmentLifecycle相应生命周期方法,这个方法然后再遍历调用所有LifecycleListener的生命周期方法。

Lifecycle.class有且只有2个方法:

public interface Lifecycle {
     

  void addListener(@NonNull LifecycleListener listener);

  void removeListener(@NonNull LifecycleListener listener);
}

ActivityFragmentLifecycle内部维持了生命周期的监听者列表:

代码片6  ActivityFragmentLifecycle.class

 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);
  }

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

  void onStop() {
     
    isStarted = false;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
     
      lifecycleListener.onStop();
    }
  }

  void onDestroy() {
     
    isDestroyed = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
     
      lifecycleListener.onDestroy();
    }
  }
}

RequestManagerFragment生命周期变化时,调用ActivityFragmentLifecycle的对应生命周期方法,其实现就是遍历生命周期监听列表,并调用监听者对应的生命周期方法,比如上面的onStart()onStop()onDestroy()方法。

那么什么时候添加监听者到ActivityFragmentLifecycle呢?答案是创建RequestManager的时候,我们看下RequestManager构成函数:

代码片7  RequestManager.class

  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);

    setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());

    glide.registerRequestManager(this);
  }

3. 小结

RequestManagerFragment生命周期变化时,调用ActivityFragmentLifecycle的对应生命周期方法。
ActivityFragmentLifecycle是在创建RequestManager的时候添加的。

另外一方面,RequestManagerFragment生命周期与Activity生命周期一致。

进而,最终将Activity生命周期与ActivityFragmentLifecycle关联起来。

二.其他情况的生命周期关联

上面分析的,只是针对在 继承FragmentActivityActivity中的情况.下面将对一般情况进行分析。

我们看一下Glide.with() 的构造方法:

代码片8  Glide.class
 @NonNull
  public static RequestManager with(@NonNull Context context) {
     
    return getRetriever(context).get(context);
  }

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

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

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

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

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

这个方法有多个重载,可以传入ContextActivityFragmentView等.但其实你会发现,上面所有getRetriever 全部是调用下面的代码:

 @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();
  }

最终都是Context上下文接收。

但代码片8中get方法却有一些不同.见RequestManagerRetriever.class

代码片9  RequestManagerRetriever.class

  @NonNull
  public RequestManager get(@NonNull 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) {
     
        return get((FragmentActivity) context);
      } else if (context instanceof Activity) {
     
        return get((Activity) context);
      } else if (context instanceof ContextWrapper) {
     
        return get(((ContextWrapper) context).getBaseContext());
      }
    }

    return getApplicationManager(context);
  }

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

  @NonNull
  public RequestManager get(@NonNull Fragment fragment) {
     
    Preconditions.checkNotNull(fragment.getActivity(),
          "You cannot start a load on a fragment before it is attached or after it is destroyed");
    if (Util.isOnBackgroundThread()) {
     
      return get(fragment.getActivity().getApplicationContext());
    } else {
     
      FragmentManager fm = fragment.getChildFragmentManager();
      return supportFragmentGet(fragment.getActivity(), fm, fragment);
    }
  }

  @NonNull
  public RequestManager get(@NonNull Activity activity) {
     
    if (Util.isOnBackgroundThread()) {
     
      return get(activity.getApplicationContext());
    } else {
     
      assertNotDestroyed(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
      return fragmentGet(activity, fm, null /*parentHint*/);
    }
  }

  @NonNull
  public RequestManager get(@NonNull 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);
  }

虽然有多个重载,但是总体上只有2种情况,即传入的是否为Application类型参数。

1. 调用getApplicationManager( ) 类型

传入Application Context或者在子线程使用:调用getApplicationManager(context);这样Glide的生命周期就和应用程序一样了。

@NonNull
  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) {
     
          // Normally pause/resume is taken care of by the fragment we add to the fragment or
          // activity. However, in this case since the manager attached to the application will not
          // receive lifecycle events, we must force the manager to start resumed using
          // ApplicationLifecycle.

          // TODO(b/27524013): Factor out this Glide.get() call.
          Glide glide = Glide.get(context.getApplicationContext());
          applicationManager =
              factory.build(
                  glide,
                  new ApplicationLifecycle(),
                  new EmptyRequestManagerTreeNode(),
                  context.getApplicationContext());
        }
      }
    }

    return applicationManager;
  }

这里获取RequestManager对象的方式和之前传入ActivityFragment对象是有所区别的,之前是创建了一个SupportRequestManagerFragment/RequestManagerFragment对象,然后获取其内部创建的Lifecycle对象作为参数传到RequestManager;而这里的主要差异是获取Lifecycle对象不一样,用的是ApplicationLifecycle,由于没有创建Fragment,这里只会调用onStart(),这种情况Glide生命周期就和Application一样长了。

class ApplicationLifecycle implements Lifecycle {
     
  @Override
  public void addListener(@NonNull LifecycleListener listener) {
     
    listener.onStart();
  }

  @Override
  public void removeListener(@NonNull LifecycleListener listener) {
     
    // Do nothing.
  }
}

2. 调用supportFragmentGet( ) /fragmentGet( ) 类型

其它情况,比如传入ActivityFragment等:最后只会调用fragmentGet() 、或者supportFragmentGet()中的一个,这样Glide就可以关联生命周期,会在生命周期不同的方法中对请求做不同的处理。

@NonNull
  private RequestManager supportFragmentGet(@NonNull Context context, @NonNull FragmentManager fm,
      @Nullable Fragment parentHint) {
     
    //创建无UI的Fragment,并绑定到当前activity
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
     
      // TODO(b/27524013): Factor out this Glide.get() call.
      Glide glide = Glide.get(context);
      //创建RequestManager,获取fragment的lifecycle,传入requestManager
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      //fragment与RequestManager关联
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }
@NonNull
  private RequestManager fragmentGet(@NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint) {
     
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
    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;
  }

2个方法等实现其实都是一样的,唯一的区别是supportFragmentGet创建的是v4包下的FragmentfragmentGet创建的是android.app.Fragment

而上述2段代码中的代码在一中第2部分 SupportRequestManagerFragment 类已经分析过了。

三.几点补充

1. pendingSupportRequestManagerFragments为什么添加fragment后又移除?

代码片4的代码再次贴出来:

代码片4   #RequestManagerRetriever.class

// pendingSupportRequestManagerFragments是一个map集合
 @VisibleForTesting
  final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
      new HashMap<>();

 @NonNull
  SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
     
       //1、由FragmentManager通过tag获取fragment
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
     
      //2、从缓存集合中获取fragment的,map以fragmentManger为key,
      //以fragment为value进行存储
      current = pendingSupportRequestManagerFragments.get(fm);
      if (current == null) {
     
        //3、创建一个fragment实例
        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();  ---(3部分会分析)分析4A
      }
    }
    return current;
  }

在第22行代码,将fragment(即fm)添加到pendingSupportRequestManagerFragments集合中,但第24行代码通过handler移除代码:

private static final int ID_REMOVE_SUPPORT_FRAGMENT_MANAGER = 2;

@Override
  public boolean handleMessage(Message message) {
     
      // .....
      //删除无关代码
    switch (message.what) {
     
      // .....
      //删除无关代码
      case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
        FragmentManager supportFm = (FragmentManager) message.obj;
        key = supportFm;
        removed = pendingSupportRequestManagerFragments.remove(supportFm);
        break;
      default:
        handled = false;
        break;
    }
     // .....
      //删除无关代码
    return handled;
  }

这里有个问题很奇怪,刚把创建的fragment对象放入map缓存起来,但是马上又通过handler把它删除,这是为什么呢?

原因是这样的,当调用FragmentManageradd()方法时,是通过开启事务的方式来进行绑定的,这个过程是异步的,具体来说,就是调用add方法时,并不是马上就和activity绑定好了,而是通过Hander来处理的。

下面来看一种应用场景:

@Override
    protected void onStart() {
     
        super.onStart();
        Glide.with(this).load("xx").into(image1);
        Glide.with(this).load("xx").into(image2)}

(1)在第一次调用第一行代码的时候,会生成一个Fragment对象,通过FragmentManager出发FragmentActivity绑定,这个绑定过程是通过Handler发消息来完成的,假设这个消息为m1;
(2)紧接着使用Handler来发送消息从HashMap中删除刚才保存的Fragment,假设这个消息为m2;
(3)由于是异步的,在消息未处理之前已经开始执行第二行Glide代码了,具体说可能是m1,m2还没有处理,就已经开始调用getSupportRequestManagerFragment方法了,这个方法内部是获取Fragment对象的,具体分析上面说过了;如果不用map来缓存fragment,那么代码流程应该是这样的:

(本来的)
 @NonNull
  SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
     
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
     
      current = pendingSupportRequestManagerFragments.get(fm);
      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;
  }

(假如不用map来缓存fragment)
 @NonNull
  SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
     
    SupportRequestManagerFragment 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;
  }

此时通过findFragmentByTag还没有找到Fragment,就会重新生成一个Fragment,这是Glide所不允许的,每一个Activity或者Fragment在使用Glide时,只能有一个所依附的虚拟的Fragment。所以将之前所生成的Fragment存储到HashMap中,这样就不会重复生成。等到SupportRequestManagerFragmentActivity绑定完成后,也就是消息m1处理完成后,再将FragmentMap中销毁。

2.性能优化建议:

Glide.with( ) 传参数时,有以下建议:

(1)尽量传递fragment或者activity, 这样可以减少通过view找到具体的fragment或者activity的步骤;

(2)尽量采用support包下的fragment/activity;一是因为兼容性;二是如果统一使用support包下的可以避免创建于与app包下FragmentManager管理的RequestManager

(3)在UI线程中调用,可以避免RequestManager生命周期与Application的一致;也尽量减少使用Application作为参数传递,也是同样的道理。


推荐阅读:

  1. Glide解析三:Glide是如何自动感应生命周期的?

  2. 13.Glide源码分析1(生命周期关联)

  3. Glide生命周期管理

你可能感兴趣的:(Android主流框架)