美文网首页
Android:Glide源码解析

Android:Glide源码解析

作者: 绿茵场上的码者 | 来源:发表于2019-07-29 17:51 被阅读0次

    1、前言

    • Android开发中,加载图片的使用场景十分常见;
    • 过去,我们可能会自己写一个加载图片框架,自己设计请求网络操作、三级缓存功能,还能凑合使用;
    • 如今,出现了大量的第三方图片加载框架,比如VolleyPicassoGlide等,可谓是让开发者事半功倍;
    • 本篇文章,并不是介绍Glide图片加载库的使用步骤,而是对Glide的设计流程、使用原理进行一个深度解剖;

    2、源码解析

    Glide.with(this).load("url").into(iv);
    

    以上代码是使用Glide最简单的写法,这样就成功的把一张图片加载到我们的控件上了,虽然说很简单,但是其内部代码到底做了怎样的操作,现在我们就一探究竟;

    2.1、获取RequestManager对象

    Glide.with(this);
    
    public static RequestManager with(FragmentActivity activity) {
        return getRetriever(activity).get(activity);
    }
    
    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();
      }
    
    

    可以看到,调用with方法是为了获取RequestManager对象,那么如何获取RequestManger对象呢?在内部调用getRetriever方法,首先会获得一个RequestManagerRetriever对象,这个对象的作用是为了创建RequestManger对象的;要获取RequestManagerRetriever对象,就要转到GlidegetRequestManagerRetriever方法中;

    public static Glide get(Context context) {
        if (glide == null) {
          synchronized (Glide.class) {
            if (glide == null) {
              checkAndInitializeGlide(context);
            }
          }
        }
        return glide;
      }
    
    private static void checkAndInitializeGlide(Context context) {
        // In the thread running initGlide(), one or more classes may call Glide.get(context).
        // Without this check, those calls could trigger infinite recursion.
        if (isInitializing) {
          throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
              + " use the provided Glide instance instead");
        }
        isInitializing = true;
        initializeGlide(context);
        isInitializing = false;
      }
    

    Glide使用了单例模式来维护,在checkAndInitializeGlide方法中实例化glide对象;

    private static void initializeGlide(Context context) {
        Context applicationContext = context.getApplicationContext();
        ···
        RequestManagerRetriever.RequestManagerFactory factory =
            annotationGeneratedModule != null
                ? annotationGeneratedModule.getRequestManagerFactory() : null;
        GlideBuilder builder = new GlideBuilder()
            .setRequestManagerFactory(factory);
        ···
        Glide glide = builder.build(applicationContext);
        ···
        Glide.glide = glide;
      }
    

    initializeGlide方法中,通过建造者模式得到glide对象;

    public Glide build(Context context) {
        if (sourceExecutor == null) {
          sourceExecutor = GlideExecutor.newSourceExecutor();//创建线程池
        }
    
        if (diskCacheExecutor == null) {
          diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
        }
    
        if (memorySizeCalculator == null) {
          memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
        }
    
        if (connectivityMonitorFactory == null) {
          connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
        }
    
        if (bitmapPool == null) {
          int size = memorySizeCalculator.getBitmapPoolSize();//创建bitmap池
          bitmapPool = new LruBitmapPool(size);
        }
    
        if (arrayPool == null) {
          arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
        }
    
        if (memoryCache == null) {
          memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());//创建内存缓存
        }
    
        if (diskCacheFactory == null) {
          diskCacheFactory = new InternalCacheDiskCacheFactory(context);
        }
    
        if (engine == null) {
          engine = new Engine(memoryCache, diskCacheFactory, diskCacheExecutor, sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor());
        }
    
        RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(
            requestManagerFactory);//创建requestManagerRetriever对象
    
        return new Glide(
            context,
            engine,
            memoryCache,
            bitmapPool,
            arrayPool,
            requestManagerRetriever,
            connectivityMonitorFactory,
            logLevel,
            defaultRequestOptions.lock());//最终实例化Glide
      }
    

    Build方法里面,创建了requestManagerRetriever对象,现在回到Glide中;

    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();
      }
    
    public RequestManagerRetriever getRequestManagerRetriever() {
        return requestManagerRetriever;
    }
    

    随后获取requestManagerRetriever对象,现在再回到with方法中,看看是怎样获取到RequestManager对象的;

    public static RequestManager with(FragmentActivity activity) {
        return getRetriever(activity).get(activity);
    }
    
    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(FragmentActivity activity) {
        if (Util.isOnBackgroundThread()) {
          return get(activity.getApplicationContext());
        } else {
          assertNotDestroyed(activity);
          FragmentManager fm = activity.getSupportFragmentManager();
          return supportFragmentGet(activity, fm, null /*parentHint*/);
        }
      }
    
      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();
          return supportFragmentGet(fragment.getActivity(), fm, fragment);
        }
      }
    
      public RequestManager get(Activity activity) {
        if (Util.isOnBackgroundThread()) {
          return get(activity.getApplicationContext());
        } else {
          assertNotDestroyed(activity);
          android.app.FragmentManager fm = activity.getFragmentManager();
          return fragmentGet(activity, fm, null /*parentHint*/);
        }
      }
    
      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.
        if (activity instanceof FragmentActivity) {
          Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
          if (fragment == null) {
            return get(activity);
          }
          return get(fragment);
        }
    
        // Standard Fragments.
        android.app.Fragment fragment = findFragment(view, activity);
        if (fragment == null) {
          return get(activity);
        }
        return get(fragment);
      }
    

    可以看到,get方法提供了不一样的参数,有ContextFragmentActivityActivityFragmentView;根据不同的使用场景进行对应的方法选择;由于我传的是FragmentActivity,所以选择该方法继续往下理解;

    public RequestManager get(FragmentActivity activity) {
        if (Util.isOnBackgroundThread()) {
          return get(activity.getApplicationContext());
        } else {
          assertNotDestroyed(activity);
          FragmentManager fm = activity.getSupportFragmentManager();//获取Fragment管理器
          return supportFragmentGet(activity, fm, null /*parentHint*/);
        }
      }
    
    private RequestManager supportFragmentGet(Context context, FragmentManager fm,
          Fragment parentHint) {
        SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);//实例化Fragment操作
        RequestManager requestManager = current.getRequestManager();//从Fragment中获取RequestFragment对象
        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());
          current.setRequestManager(requestManager);//假如requestManager为null的话,就实例化一个放到该Fragment中
        }
        return requestManager;//最终返回RequestManager对象
      }
    
    SupportRequestManagerFragment getSupportRequestManagerFragment(
          final FragmentManager fm, Fragment parentHint) {
        SupportRequestManagerFragment current =
            (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
          current = pendingSupportRequestManagerFragments.get(fm);
          if (current == null) {
            current = new SupportRequestManagerFragment();//实例化一个Fragment
            current.setParentFragmentHint(parentHint);
            pendingSupportRequestManagerFragments.put(fm, current);
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();//加入到Fragment管理器中
            handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
          }
        }
        return current;
      }
    
    

    从以上代码可知,首先从Activity中获取了Fragment管理器,然后新建一个SupportRequestManagerFragment对象,其实它就是一个Fragment对象,然后把Fragment添加到fm管理器中,与当前Activity的生命周期进行绑定,这样的设计很巧妙,SupportRequestManagerFragment对象管理着Glide的生命周期,这样就能把Glide生命周期和Activity生命周期进行一个绑定,比如当Activity处于后台状态时,Glide就会停止加载或者Activity销毁了Glide也会销毁,这样能更好的节省流量、防止内存泄露等问题;最终从Fragment对象中得到RequestManager对象;然而说了那么多,RequestManager对象到底有什么作用,实际上说白了,它的作用就是对Glide图片加载请求进行一个管理;

    2.2、构建RequestBuilder对象

    load("url")
    
    public RequestBuilder<Drawable> load(@Nullable Object model) {
        return asDrawable().load(model);
    }
    
    public RequestBuilder<Drawable> asDrawable() {
        return as(Drawable.class).transition(new DrawableTransitionOptions());
    }
    
    public <ResourceType> RequestBuilder<ResourceType> as(Class<ResourceType> resourceClass) {
        return new RequestBuilder<>(glide, this, resourceClass);
    }
    
    public RequestBuilder<TranscodeType> load(@Nullable Object model) {
        return loadGeneric(model);
      }
    
      private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
        this.model = model;
        isModelSet = true;
        return this;
    }
    

    很简单,把Glide对象和RequestManager对象传入RequestBuilder中,构建RequestBuilder对象;

    2.3、加载图片

    into(iv);
    
    public Target<TranscodeType> into(ImageView view) {
        ```
        if (!requestOptions.isTransformationSet()
            && requestOptions.isTransformationAllowed()
            && view.getScaleType() != null) {
          if (requestOptions.isLocked()) {
            requestOptions = requestOptions.clone();
          }
          switch (view.getScaleType()) {
            case CENTER_CROP:
              requestOptions.optionalCenterCrop();
              break;
            case CENTER_INSIDE:
              requestOptions.optionalCenterInside();
              break;
            case FIT_CENTER:
            case FIT_START:
            case FIT_END:
              requestOptions.optionalFitCenter();
              break;
            case FIT_XY:
              requestOptions.optionalCenterInside();
              break;
            case CENTER:
            case MATRIX:
            default:
              // Do nothing.
          }
        }
    
        return into(context.buildImageViewTarget(view, transcodeClass));
      }
    
    

    在into方法里面,设置ImageView控件的显示方式;

    public <X> Target<X> buildImageViewTarget(ImageView imageView, Class<X> transcodeClass) {
        return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
      }
    
    public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {
        if (Bitmap.class.equals(clazz)) {
          return (Target<Z>) new BitmapImageViewTarget(view);
        } else if (Drawable.class.isAssignableFrom(clazz)) {
          return (Target<Z>) new DrawableImageViewTarget(view);
        } else {
          throw new IllegalArgumentException(
              "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
        }
      }
    
    

    根据传入的参数,设置BitmapImageViewTarget对象;

    public class BitmapImageViewTarget extends ImageViewTarget<Bitmap> {
      public BitmapImageViewTarget(ImageView view) {
        super(view);
      }
    
      @Override
      protected void setResource(Bitmap resource) {
        view.setImageBitmap(resource);
      }
    }
    

    Bitmap为例子,在该类里,就是把Bitmap设置到ImageView上,回到into方法中;

    public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
        Util.assertMainThread();
        Preconditions.checkNotNull(target);
        if (!isModelSet) {
          throw new IllegalArgumentException("You must call #load() before calling #into()");
        }
    
        Request previous = target.getRequest();
    
        if (previous != null) {
          requestManager.clear(target);
        }
    
        requestOptions.lock();
        Request request = buildRequest(target);//构建请求体
        target.setRequest(request);//把请求体设置到target中
        requestManager.track(target, request);
    
        return target;
      }
    

    假如该控件已经存在一个请求体,那么就移除掉,然后重新创建请求体,并且设置到控件Target中,最终调用track方法加载;

    private Request buildRequest(Target<TranscodeType> target) {
        return buildRequestRecursive(target, null, transitionOptions, requestOptions.getPriority(),
            requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight());
      }
    
      private Request buildRequestRecursive(Target<TranscodeType> target,
          @Nullable ThumbnailRequestCoordinator parentCoordinator,
          TransitionOptions<?, ? super TranscodeType> transitionOptions,
          Priority priority, int overrideWidth, int overrideHeight) {
          ···
    
          int thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();
          int thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();
          if (Util.isValidDimensions(overrideWidth, overrideHeight)
              && !thumbnailBuilder.requestOptions.isValidOverride()) {
            thumbOverrideWidth = requestOptions.getOverrideWidth();
            thumbOverrideHeight = requestOptions.getOverrideHeight();
          }
    
          ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
          Request fullRequest = obtainRequest(target, requestOptions, coordinator,
              transitionOptions, priority, overrideWidth, overrideHeight);
          isThumbnailBuilt = true;
          // Recursively generate thumbnail requests.
          Request thumbRequest = thumbnailBuilder.buildRequestRecursive(target, coordinator,
              thumbTransitionOptions, thumbPriority, thumbOverrideWidth, thumbOverrideHeight);
          isThumbnailBuilt = false;
          coordinator.setRequests(fullRequest, thumbRequest);
          return coordinator;
        } else if (thumbSizeMultiplier != null) {
          ···
        } else {
          // Base case: no thumbnail.
          return obtainRequest(target, requestOptions, parentCoordinator, transitionOptions, priority,
              overrideWidth, overrideHeight);
        }
      }
    
      private Request obtainRequest(Target<TranscodeType> target,
          RequestOptions requestOptions, RequestCoordinator requestCoordinator,
          TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority,
          int overrideWidth, int overrideHeight) {
        requestOptions.lock();
    
        return SingleRequest.obtain(
            context,
            model,
            transcodeClass,
            requestOptions,
            overrideWidth,
            overrideHeight,
            priority,
            target,
            requestListener,
            requestCoordinator,
            context.getEngine(),
            transitionOptions.getTransitionFactory());
      }
    

    根据设置指定的图片宽高进行加载,最终获取SingleRequest对象;构建好后继续往下;

    void track(Target<?> target, Request request) {
        targetTracker.track(target);
        requestTracker.runRequest(request);
      }
    
    public void track(Target<?> target) {
        targets.add(target);
      }
    
    

    Target放到Set集合中;以便统一管理;

    public void runRequest(Request request) {
        requests.add(request);
        if (!isPaused) {
          request.begin();
        } else {
          pendingRequests.add(request);
        }
      }
    

    调用begin方法执行请求;


    3、总结

    • 在当前Activity中新建Fragment并且与之相关联,让Glide的生命周期和Activity生命周期同步;
    • 可以自定义需要加载的图片宽高;

    相关文章

      网友评论

          本文标题:Android:Glide源码解析

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