美文网首页
Glide解析三:Glide是如何自动感应生命周期的?

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

作者: jxiang112 | 来源:发表于2019-02-22 11:34 被阅读15次

    Glide解析一:Glide整体流程中,我们知道RequestManager是主要用来管理、启动图片加载请求的。而它是通过RequestManagerRetriever创建、获取的。

    1、为什么用RequestManagerRetriever来获取RequestManager?

    RequestManagerRetriever.java
    为什么用RequestManagerRetriever来获取RequestManager?而不直接使用RequestManager的单例?我们通过常用的使用方式来分析其原因:

    public RequestManager get(@NonNull View view) {
        if (Util.isOnBackgroundThread()) {
          //如果是在非UI线程,则使用绑定Application生命周期的RequestManager
          return get(view.getContext().getApplicationContext());
        }
    
        Preconditions.checkNotNull(view);
        Preconditions.checkNotNull(view.getContext(),
            "Unable to obtain a request manager for a view without a Context");
        //根据view拿到activity
        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.
        //如果使用的是support中的activity
        if (activity instanceof FragmentActivity) {
          //如果是FragmentActivity
          //如果view是support fragment中的,则根据view获取其所在的support fragment,接着调用get(fragment)
          //如果view是FragmentActivity中,则调用get(FragmentActivity)方法
          Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
          return fragment != null ? get(fragment) : get(activity);
        }
         //如果没有support中的组件,其原理与support中的activity一样,不展开讲解
        // Standard Fragments.
        android.app.Fragment fragment = findFragment(view, activity);
        if (fragment == null) {
          return get(activity);
        }
        return get(fragment);
      }
    
    private Fragment findSupportFragment(@NonNull View target, @NonNull FragmentActivity activity) {
        //清空view和fragment关联列表
        tempViewToSupportFragment.clear();
        //从activity的所有fragment中找出fragment的根view,并将根view与fragment进行关联存放view和fragment关联列表tempViewToSupportFragment中
        findAllSupportFragmentsWithViews(
            activity.getSupportFragmentManager().getFragments(), tempViewToSupportFragment);
        Fragment result = null;
        View activityRoot = activity.findViewById(android.R.id.content);
        View current = target;
        while (!current.equals(activityRoot)) {
          //从view和fragment关联列表中获取view所关联的fragment
          result = tempViewToSupportFragment.get(current);
          if (result != null) {
            break;
          }
          if (current.getParent() instanceof View) {
            //获取当前view的父级view
            current = (View) current.getParent();
          } else {
            break;
          }
        }
    
        tempViewToSupportFragment.clear();
        return result;
      }
     
    private static void findAllSupportFragmentsWithViews(
          @Nullable Collection<Fragment> topLevelFragments,
          @NonNull Map<View, Fragment> result) {
        if (topLevelFragments == null) {
          return;
        }
        for (Fragment fragment : topLevelFragments) {
          //遍历fragment
          // getFragment()s in the support FragmentManager may contain null values, see #1991.
          if (fragment == null || fragment.getView() == null) {
            continue;
          }
          //将fragment的根view与fragment进行关联
          result.put(fragment.getView(), fragment);
          findAllSupportFragmentsWithViews(fragment.getChildFragmentManager().getFragments(), result);
        }
      }
    

    一般我们都是使用support 中的fragmetactivity,所以get(view)要么转到get(Fragment)中要么转到get(FragmentActivity)中。这里先根据view找到其所在fragment的思路是拿当前view的根view与activity的所有fragment的根view进行比较,如果相等,则这个fragment就是我们要找的fragment。

    1.1、get(Fragment) 的实现逻辑
    public RequestManager get(@NonNull Fragment fragment) {
          //...
          //获取fragment的子FragmentManager
          FragmentManager fm = fragment.getChildFragmentManager();
          //调用supportFragmentGet
          return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
        }
      }
    
    
    private RequestManager supportFragmentGet(
          @NonNull Context context,
          @NonNull FragmentManager fm,
          @Nullable Fragment parentHint,
          boolean isParentVisible) {
        //根据FragmentManager获取已经存在的SupportRequestManagerFragment 或者创建一个新的SupportRequestManagerFragment 
        SupportRequestManagerFragment current =
            getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
        //获取与fragment关联的RequestManager
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
          // TODO(b/27524013): Factor out this Glide.get() call.
          //RequestManager为空
          Glide glide = Glide.get(context);
          //构建一个新的RequestManager
          requestManager =
              factory.build(
                  glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
          //将fragment与RequestManager进行关联
          current.setRequestManager(requestManager);
        }
        return requestManager;
      }
    

    get(Fragment)获取SupportRequestManagerFragment 的逻辑我们看下其代码实现:

    private SupportRequestManagerFragment getSupportRequestManagerFragment(
          @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
        //根据tag名称从FragmentManager中查找SupportRequestManagerFragment 
        SupportRequestManagerFragment current =
            (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
          //如果FragmentManager没有SupportRequestManagerFragment 
          //从等待FragmentManager添加Fragment完成列表中获取SupportRequestManagerFragment 
          current = pendingSupportRequestManagerFragments.get(fm);
          if (current == null) {
            ////如果没有SupportRequestManagerFragment 
            //创建新的SupportRequestManagerFragment
            current = new SupportRequestManagerFragment();
            //将新创建的fragment加到其父级fragment列表中
            current.setParentFragmentHint(parentHint);
            if (isParentVisible) {
              //如果父级可见,回调生命周期的onStart
              current.getGlideLifecycle().onStart();
            }
            //将创建的fragment加入等待FragmentManager添加fragment的队列中
            pendingSupportRequestManagerFragments.put(fm, current);
            //将创建的fragment加入FragmentManager中
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
            //发送消息,从等待FragmentManager添加fragment的队列中删除fragment
            handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
          }
        }
        return current;
      }
    

    根据上面的代码分析可以归纳RequestManagerRetriever创建或者获取RequestManager的流程:

    • 如果在子线程,则创建一个生命周期与Application一样的RequestManager
    • 根据view先拿到其所属的fragment或者activity
    • 从当前framgnet或者activity中获取RequestManagerFragment,如果不为空则返回与之关联的RequestManager;如果为空那么创建一个新的RequestManagerFragment,创建的情况下顺便创建RequestManager,并进行关联,并返回该RequestManager
      根据这段代码有2个问题,
      问题1:为什么使用pendingSupportRequestManagerFragments来添加RequestManagerManager?fm添加RequestManagerFragment之后又发送消息删除该RequestManagerFragment呢?
      答案:因为fm添加fragment不是调用add方法就代表添加完成的,它有相关的生命周期是异步进行的,所以如果add之后立马又在相同fragment或者activity环境中调用get方法,那么就很有可能又创建一个新的RequestManagerFragment,而pendingSupportRequestManagerFragments就是为了杜绝重复创建RequestManagerFragment而准备的。
      问题2:对于glide的get使用有什么优化的地方吗?
      答案:
    • 尽量不要在子线程中调用,因为子线程调用意味着生命周期是全局的,不能跟activity或fragment的生命周期同步
    • get的时候最好传activity、或者fragment,因为这样可以减少查找具体的fragment或者activity的步骤
      问题3:为什么要用RequestManagerFragment并与RequestManager进行关联呢?
      答案:是为了进行自动感应组件的生命周期
    2、为什么要用RequestManagerFragment并与RequestManager进行关联?

    步骤1中分析了get的流程中,fragment和activity最终是通过创建RequestManagerFragment并和RequestManager进行关联
    我们看下RequestManagerFragment的几个关键生命周期函数:

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

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

    class ActivityFragmentLifecycle implements Lifecycle {
      private final Set<LifecycleListener> lifecycleListeners =
          Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
      //...
    }
    

    当RequestManagerFragment生命周期变化时,调用ActivityFragmentLifecycle的对应生命周期方法,其实现就是遍历生命周期监听列表,并调用监听者对应的生命周期方法:

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

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

    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 we're the application level request manager, we may be created on a background thread.
        // In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
        // issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
        // This should be entirely safe.
        if (Util.isOnBackgroundThread()) {
          //如果是自线程,则切换到主线程监听生命周期
          mainHandler.post(addSelfToLifecycle);
        } else {
          //监听生命周期
          lifecycle.addListener(this);
        }
        //生命周期变化时,相应的监听网络状态和取消监听网络装
        lifecycle.addListener(connectivityMonitor);
    
        setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
    
        glide.registerRequestManager(this);
      }
    

    ok,最后我们总结下Glide是如何自动感应生命周期的:

    • 如果是在子线程,这Glide使用的RequestManager与Application一样的生命周期
    • 如果是fragment、activity,则使用FragmentManagerFragment与RequestManager进行关联,通过FragmentManagerFragment的生命周期变化来调度RequestManager对图片加载请求Request采取暂停、重新开始、停止等操作。
      因为Android有fragment、support包中的fragment、activity、surport中的activity,因为使用FragmentManagerFragment来实现RequestManager感应生命周期,这几个fragmengt、activity使用的FragmentManager各自不同,如果是fragment在用ChildFragmentManager或者support中的ChildFragmentManager;如果是activity则用FragmentManager或者support中的FragmentManager。所以RequestManagerRetriever主要用来根据framgnet、activity来创建对应的RequestManager。
      问题:Glide中最多有几个RequestManager?
      答案:5个,分别是:
    • 与Application生命周期一致的RequestManager
    • 与app包下activity的FragmentManager关联的RequestManager
    • 与app包下fragment的ChildFragmentManager关联的RequestManager
    • 与support包下activity的FragmentManager关联的RequestManager
    • 与support包下fragment的ChildFragmentManager关联的RequestManager
      问题:Glide的get操作有哪些优化点?
      答案:
    • 在UI线程中调用,可以避免RequestManager生命周期与Application的一直
    • 尽量采用support报下的fragment/activity;一是因为兼容性;二是如果统一使用support包下的可以避免创建于与app包下FragmentManager管理的RequestManager
    • get尽量传递fragment或者activity,这样可以减少通过view找到具体的fragment或者activity的步骤

    相关文章

      网友评论

          本文标题:Glide解析三:Glide是如何自动感应生命周期的?

          本文链接:https://www.haomeiwen.com/subject/izbryqtx.html