美文网首页
Glide 之生命周期管理

Glide 之生命周期管理

作者: 努力做一个最懒的程序员 | 来源:发表于2019-06-20 11:57 被阅读0次

Glide 中运用到的优秀技术有很多值得我们深入学习,这篇文章就来介绍一下 Glide 的生命周期是如何与 Activity、Fragment 进行绑定的。

一、with()入参分类

Glide.with(arg)可以接收 ActivityFragmentActivityFragmentv4.FragmentContextView 六种类型,然后通过 RequestManagerRetriever 获取 RequestManager。

1.Context、View

这两种方法都是先确定其类型,如果它的 Context 不属于 Activity、FragmentActivity、Fragment、v4.Fragment 则生命周期与应用同步,无需处理。

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

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

2.FragmentActivity、Activity

这两个只有 FragmentManager 不同,其他流程都相同。

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

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

3.Fragment、v4.Fragment

可以看到这两种类型在调用 ***fragmentGet()时多传了一个 fragment。而 fragmentGet 与 supportFragmentGet 没有太大区别,

  @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
  public RequestManager get(android.app.Fragment fragment) {
    if (fragment.getActivity() == null) {
      throw new IllegalArgumentException(
          "You cannot start a load on a fragment before it is attached");
    }
    if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
      return get(fragment.getActivity().getApplicationContext());
    } else {
      android.app.FragmentManager fm = fragment.getChildFragmentManager();
      // fragmentGet
      return fragmentGet(fragment.getActivity(), fm, fragment);
    }
  }

  public RequestManager get(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();
      // supportFragmentGet
      return supportFragmentGet(fragment.getActivity(), fm, fragment);
    }
  }

二、fragmentGet() 与 supportFragmentGet()

fragmentGet()supportFragmentGet() 两个函数原理其实相同,所以这里就 fragmentGet 来进行讲解。

这个函数中有两个类是实现生命周期管理的核心 RequestManagerFragment 和 RequestManager。

  private RequestManager fragmentGet(Context context, android.app.FragmentManager fm,
      android.app.Fragment parentHint) {
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

三、RequestManager 与 RequestManagerFragment 的合作

RequestManager 实现了 LifecycleListener 接口,用于管理 Glide 的请求,可以同步 Activity、Fragment 生命周期进行启动、停止、重启操作。

RequestManagerFragment作为一个无视图的 Fragment 可以和当前的 Activity 或者 Fragment 进行绑定,这样在自己的生命周期就可以同步监听到它们的生命周期,通过 ActivityFragmentLifecycle 将 RequestManager 进行生命周期同步。

childRequestManagerFragments 用于存放当前 Activity 下所有的 RequestManagerFragment;RequestManagerTreeNode 存储了此 RequestManagerFragment 的父元素所对应的一组Fragment。这样层层嵌套,保证了上层变动后下层可以实时更新。

  @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
  RequestManagerFragment getRequestManagerFragment(
      final android.app.FragmentManager fm, android.app.Fragment parentHint) {
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
      current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        pendingRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

getRequestManagerFragment 会从 FragmentManager 中查找当前 Activity 或者 Fragment 是否已经创建过标记为 FRAGMENT_TAG 的 RequestManagerFragment,如果没有找到会将其创建并添加到 FragmentManager 中。

可以看到新创建的 RequestManagerFragment 刚刚放入 pendingRequestManagerFragments,但是紧接着又调用 handler 将其移除了,这是为了防止同一个界面创建多个 RequestManagerFragment。

总结

所以 Glide 管理生命周期的整体流程就是先创建一个无视图的 Fragment,并同时创建这个 Fragment 的 ActivityFragmentLifeCycle 对象,当这个 Framgent 的生命周期发生变化时会调用 ActivityFragmentLifeCycle 使其中的 RequestManager 做出对应处理,由 RequestTracker 具体实现。

相关文章

  • Glide内存管理

    1.前言 Glide框架的核心内容主要包含生命周期自动管理和内存管理,生命周期管理在《Glide源码分析-生命周期...

  • Glide原理之执行流程分析

    Glide是一个优秀的图片加载库,它有如下优点: Glide可以监听Activity的生命周期管理,更加合理的管理...

  • Glide 系列(六)Glide中的线程中断实现

    Glide生命周期管理 Glide非常优秀的一个特色是实现对生命的周期的管理,通过对ImageView所属的Act...

  • Glide 之生命周期管理

    Glide 中运用到的优秀技术有很多值得我们深入学习,这篇文章就来介绍一下 Glide 的生命周期是如何与 Act...

  • 动脑学院Glide预习资料 生命周期管理

    Glide生命周期管理 本文是Glide源码解析系列的第一篇,通过这篇文档,将可以了解到: 1.Glide如何绑定...

  • Glide如何自动管理生命周期

    Glide管理生命周期还是很有想法的,这种思路值得我们去学习和应用; 特点 实现原理 源码分析 Glide.wit...

  • Glide与Picasso的区别

    Glide使用生命周期对图片进行管理,根据Glide的使用方法我们可以看出,传入的context建议传入Activ...

  • Glide生命周期管理

    Glide生命周期管理 1.Glide特点 使用简单 可配置度高,自适应程度高 支持常见图片格式(jpg、png、...

  • Android Glide(二)生命周期感知

    Glide的生命周期管理 主要分为三个层次的生命周期:Activity & 网络 & 内存。我们一般认为,应该及时...

  • Glide4.5源码分析二

    这篇摸清一个问题,Glide是怎么实现生命周期管理的?前面已经分析过Glide通过创建一个隐藏的fragment添...

网友评论

      本文标题:Glide 之生命周期管理

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