Glide源码——RequestManagerRetriever

RequestManagerRetriever类负责RequestManager的创建,并通过创建RequestManagerFragment / SupportRequestManagerFragment 并与RequestManager进行绑定,来赋予RequestManager生命周期。这篇文章会涉及到com.bumptech.glide.manager目录下这么几个文件:

RequestManagerRetriever、RequestManagerFragment、SupportRequestManagerFragment、LifecycleListener、Lifecycle、ApplicationLifecycle、ActivityFragmentLifecycle

https://zhuanlan.zhihu.com/p/110571767

上面的链接讲解的很详细,从上面copy了一些内容,如下

Glide:供外部调用的核心类,外观模式;
RequestManagerRetriever:是关联RequestManager和SupportRequestManagerFragment/RequestManagerFragment的中间类;
RequestManager:是用来加载、管理图片请求的,会结合Activity/Fragment生命周期对请求进行管理;
SupportRequestManagerFragment/RequestManagerFragment:Glide内部创建无UI的fragment,会与当前Activity绑定,与RequestManager绑定,传递页面的生命周期。其中SupportRequestManagerFragment是v4包下的Fragment,RequestManagerFragment:Glide是android.app.Fragment;
ActivityFragmentLifecycle:保存fragment和Requestmanager映射关系的类,管理LifecycleListener;
LifecycleListener:定义生命周期管理方法的接口,onStart(), onStop(), onDestroy()。
ApplicationLifecycle:同Application的生命周期;

1、在使用Glide的时候尽量传入Activity或者Fragment的,这样才能绑定/关联生命周期;使用ApplicationContext的话会使得Glide生命周期和Application一样长;

2、在UI线程中调用Glide,在子线程使用的话会和使用ApplicationContext一样;

3、Glide关联生命周期主要分为2个部分:如何感应当前页面的生命周期?通过创建一个无UI的Fragment来实现;如何传递生命周期?RequestManager与Fragment之间通过Lifecycle、LifecycleListener接口回调的方式来实现。更详细的可以看第二部分的小结。

核心代码举例:

private RequestManager supportFragmentGet(
    @NonNull Context context,
    @NonNull FragmentManager fm,
    @Nullable Fragment parentHint,
    boolean isParentVisible) {
  SupportRequestManagerFragment current =
      getSupportRequestManagerFragment(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;
}
private SupportRequestManagerFragment getSupportRequestManagerFragment(
    @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
  SupportRequestManagerFragment current =
      (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
  if (current == null) {
    current = pendingSupportRequestManagerFragments.get(fm);
    if (current == null) {
      current = new SupportRequestManagerFragment();
      current.setParentFragmentHint(parentHint);
      if (isParentVisible) {
        current.getGlideLifecycle().onStart();
      }
      pendingSupportRequestManagerFragments.put(fm, current);
      fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
      handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
    }
  }
  return current;
}

创建RequestManagerFragment和RequestManager是分开,都创建完毕后再通过setRequestManager()方法把他们关联起来,RequestManager实现了LifecycleListener方法,会被RequestManagerFragment相应的生命周期回调到。

这里有个问题很奇怪,刚把创建的fragment对象放入map缓存起来,但是马上又通过handler把它删除,这是什么情况?
原因是这样的,当调用FragmentManager的add()方法时,是通过开启事务的方式来进行绑定的,这个过程是异步的,具体来说,就是调用add方法时,并不是马上就和activity绑定好了,而是通过Hander来处理的。此时通过findFragmentByTag还没有找到Fragment,就会重新生成一个Fragment,这是Glide所不允许的,每一个Activity或者Fragment在使用Glide时,只能有一个所依附的虚拟的Fragment。所以将之前所生成的Fragment存储到HashMap中,这样就不会重复生成。等到SupportRequestManagerFragment与Activity绑定完成后,再通过Handler发消息将Fragment从Map中销毁。

汇总下,无论使用什么参数,最终都会进入如下三个方法创建 RequestManager:

RequestManager fragmentGet(Context context, android.app.FragmentManager fm);
RequestManager supportFragmentGet(Context context, android.support.v4.app.FragmentManager fm);
RequestManager getApplicationManager(Context context);

activity调用Activity.getFragmentManager()、fragment调用Fragment.getChildFragmentManager()、FragmentActivity调用FragmentActivity.getSupportFragmentManager();来得到FragmentManager,从而将创建的不包含UI元素的Fragment加入到FragmentManager的管理中,从而传递生命周期。

注意Activity自身是有 getFragmentManager()方法的。

Glide通过参数Context context来找到对应的activity,方法实现:

private Activity findActivity(@NonNull Context context) {
  if (context instanceof Activity) {
    return (Activity) context;
  } else if (context instanceof ContextWrapper) { //ContextWrapper继承自Context,是一个包装类(代理类,使用了装饰者模式),里面的方法都是又mBase代理实现的,而mBase一般都是ContextImpl。
    return findActivity(((ContextWrapper) context).getBaseContext());
  } else {
    return null;
  }
}

注意以下几个结论:
1.在子线程调用Glide#with()方法或传入Context对象为ApplicationContext,此时会创建一个全局唯一的 RequestManager,生命周期与APP周期保持一致,即上面的getApplicaitonManager(),为什么子线程调用会使用到getApplicationManager(),我猜测是考虑到子线程不好控制生命周期容易引起内存泄漏才这样做的;
2.同一个Activity对应一个FragmentManager,一个FragmentManager对应一个RequestManagerFragment,一个 RequestManagerFragment对应一个RequestManager,所以一个Activity对应一个RequestManager;
3.同一个Fragment同样可得出上述结论;
4.但如果Fragment属于Activity,或者Fragment属于Fragment,在Activity、Framgnent中分别创建Glide请求是并不会只创建一个RequestManager;

还有一个细节,除了通过get(Context context)来获取绑定了生命周期的RequestManager外,还有一个很少用的get(View view)方法,该方法的目的是经可能地找到生命周期最短的那个FragmentManger,做法是先通过View.getContext()查找activity,如果activity是FragmentActivity,那么查找Fragment,如果有Fragment,则通过Fragment去创建,否则通过activity创建。

查找Fragment的算法:FragmentManager.getFragments()得到所有的Fragment,再不断递归到每一个Fragment,调用Fragment.getView(),以(view, fragment)形式保存到map里。再从view开始向上不断getParent()迭代,直到根节点android.R.id.content,迭代过程中找到某个view在map中存在,就找到了目标fragment。

代码如下:

public RequestManager get(@NonNull View view) {
  if (Util.isOnBackgroundThread()) {
    return get(view.getContext().getApplicationContext());
  }
  ...
  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);
}
private static void findAllSupportFragmentsWithViews(
    @Nullable Collection<Fragment> topLevelFragments,
    @NonNull Map<View, Fragment> result) {
  if (topLevelFragments == null) {
    return;
  }
  for (Fragment fragment : topLevelFragments) {
    // getFragment()s in the support FragmentManager may contain null values, see #1991.
    if (fragment == null || fragment.getView() == null) {
      continue;
    }
    result.put(fragment.getView(), fragment);
    findAllSupportFragmentsWithViews(fragment.getChildFragmentManager().getFragments(), result);
  }
}

@Nullable
private Fragment findSupportFragment(@NonNull View target, @NonNull FragmentActivity activity) {
  tempViewToSupportFragment.clear();
  findAllSupportFragmentsWithViews(
      activity.getSupportFragmentManager().getFragments(), tempViewToSupportFragment);
  Fragment result = null;
  View activityRoot = activity.findViewById(android.R.id.content);
  View current = target;
  while (!current.equals(activityRoot)) {
    result = tempViewToSupportFragment.get(current);
    if (result != null) {
      break;
    }
    if (current.getParent() instanceof View) {
      current = (View) current.getParent();
    } else {
      break;
    }
  }

  tempViewToSupportFragment.clear();
  return result;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值