glide4.9.0源码解析

引用

implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'

使用

    Glide.with(GlideActivity.this)
                .load(url)
                .centerCrop()
                .placeholder(R.mipmap.ic_launcher)
                .error(R.mipmap.ic_launcher)
                .transform(new GlideCircleTransform(CommonStaffSelectedForRoleActivity.this))
                .into(imageView);

优点

  • Glide可以监听Activity的生命周期管理,更加合理的管理图片的加载和释放。

  • Glide可以加载Gif图。

  • 缓存策略和加载速度。Picasso缓存的是全尺寸,而Glide的缓存的图片和ImageView的尺寸相同。Glide的这个特点,让加载显得特别的快,而Picasso则因为需要在显示之前重新调整大小而导致一些延迟。

  • Glide可以通过自定义GlideMoudle来完成特殊的加载需求,例如加载加密的图片等

源码分析

源码太多,只能根据一条主线走下去,也就是Glide三个重要方法,with,load,into。

with

那么glide是怎样通过with传入的参数。如何绑定生命周期?如何传递生命周期?
首先从glide的静态方法with分析。

     @NonNull
    public static RequestManager with(@NonNull View view) {
    
    
    return getRetriever(view.getContext()).get(view);
    }
    @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 Fragment fragment) {
    
    
    return getRetriever(fragment.getActivity()).get(fragment);
    }

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

参数可以是with的参数可以是android.app.Activity、android.app.Fragment、android.support.v4.app.Fragment、android.support.v4.app.FragmentActivity等。

    @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();
    }
内部都是通过getRetriever方法获取RequestManagerRetriever对象再调用get方法。

     @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, /*parentHint=*/ null, isActivityVisible(activity));
    }
    }

    @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, fragment.isVisible());
    }
    }

    @SuppressWarnings("deprecation")
    @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, /*parentHint=*/ null, isActivityVisible(activity));
    }
    }
    ……

通过get方法内部可以看出,通过将fm作为参数最后调用supportFragmentGet 或者fragmentGet返回一个RequestManager对象。那么这个RequestManager对象是干嘛的呢?接着下面看。

     @NonNull
    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;
    }
原来RequestManager是通过current(RequestManagerFragment)对setRequestManager设置的。首先看下getSupportRequestManagerFragment是怎么获取的RequestManagerFragment对象。

       @NonNull
    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;
    }

SupportRequestManagerFragment初始化的时候,需要创建一个ActivityFragmentLifecycle,初始化成员变量lifecycle。

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

    @VisibleForTesting
    @SuppressLint("ValidFragment")
    public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
    
    
    this.lifecycle = lifecycle;
    }

然后看到了下面这句

     fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();

原来通过当前activity的fm管理器添加将空页面的SupportRequestManagerFragment的fragment添加进去,并返回这个空页面的fragment。

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

再来看通过current.getLifecycle()获取fragment的lifecycle,传入requestManager,将fragment和requestManager建立联系。

load

load方法主要是加载网络地址,图片资源,可以是本地图片、应用资源、二进制流、uri对象。

into

缓存相关

Glide资源加载流程,内存缓存加载

内存缓存分为两部分,弱引用持有的活动缓存和LruCache管理的非活动缓存。

什么叫活动缓存,就是该图片有被用来显示就是活动的,如果没有被显示,就是非活动的。

因此活动的图片缓存没有必要放入LruCache管理,因为此时它不应该被回收,而如果该图片不再被显示了,也就是release为0了之后,就会重新放入非活动缓存中由LruCache管理它的缓存,因此LruCache管理的内存缓存大小并不包含正在显示的图片

Glide磁盘缓存资源加载

  • **ALL: **缓存原始数据和转换后的数据
  • **NONE: **不缓存
  • **DATA: **原始数据,未经过解码或者转换
  • **RESOURCE: **缓存经过解码的数据
  • **AUTOMATIC(默认):**根据EncodeStrategyDataSource等条件自动选择合适的缓存方

猜你喜欢

转载自blog.csdn.net/f917386389/article/details/91048294