美文网首页Android 进阶之旅
Android 进阶学习(十二) Glide源码学习(一) 图片

Android 进阶学习(十二) Glide源码学习(一) 图片

作者: Tsm_2020 | 来源:发表于2020-12-01 16:42 被阅读0次

    Glide 作为Google 出品的图片加载库,在开发的过程中对我们的帮助是非常大的,网上也有很多关于他的文章,说他怎么怎么好,但是他就是再好我们如果不知道他的原理也肯定是记不住的,而且关于图片的操作在面试过程中是必然要问到的,如果你只是知道怎么用的话肯定是不能打动面试官的,如果你能从源码方面说一下,肯定会让对方眼前一亮的,废话不多说,我们由简入繁的开始分析一下一张图片在Glide都经历了什么,

    想要弄清楚整个图片的加载过程,如果上来就看源码的话大家肯定会非常懵,还是需要先弄清楚每个类在Glide中扮演的角色,这样便于大家的理解,即使部分代码不懂,但是知道了他是干什么也能猜测一个大概,同时也方便我们在分析过程中查看

    Glide 中重要的角色

    1.Glide

    Glide作为图片加载的入口, 当中保存着非常重要的数据,在整个请求中非常重要,创建方式: DCL 单例

    2.RequestManagerRetriever

    RequestManagerRetriever 作为RequestManager 管理者,调度着当前请求应该分配给哪个RequestManager,创建方式:new 伴随着Glide同时创建

    3.RequestManager

    RequestManager 作为请求的承载者,中控器, 在当中扮演着非常重要的角色, 创建方式: new 不同的是并不是每次请求都创建,而是在同一个activity中只创建一个,部分情况可能将这个请求分配给ApplicationContext,

    4.Request

    这个一看就知道是请求, 重要的请求类 SingleRequest ThumbnailRequestCoordinator (包含2个请求,判断也非常简单,后面我们会单独做分析)
    创建方式 : 缓存池 ,防止大量创建对象浪费时间,频繁销毁对象导致内存抖动,同样的方式 Handler.obtainMessage 也是如此

    5.RequestBuilder

    用来构建请求时的参数,通常会继承开发者在全局的配置,如果有改动会替换响应的改动.创建方式:new 无特殊方式,但是需要注意的是RequestBuilder的创建开始的方法是 as(classType.class) ,即使是Glide.with(context).load(resId),看似我们是调用的load 的方法创建了这个RequestBuilder,实际操作还是调用的as 方法

     @NonNull
     @CheckResult
     @Override
     public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
       return asDrawable().load(resourceId);
     }
     @NonNull
     @CheckResult
     public RequestBuilder<Drawable> asDrawable() {
       return as(Drawable.class);
     }
    

    6.Target

    Target 是作为回调参与进来的,他不仅仅参与下载后作为最后资源出口,还会参与下载过程中获取图片的载体的宽高等等,

    7.Engine

    Engine 的做用是发起请求,实际的请求过程就是在他的内部实现的,创建方式:new 伴随着Glide 创建的

    至此整个加载过程中涉及到的角色我们就分析完了,下面我们进入正题,开始分析一下最简单的请求

    Glide.with(context).load(resId).into(imageView);
    

    Glide.with(context)

     @NonNull
     public static RequestManager with(@NonNull Context context) {
       return getRetriever(context).get(context);
     }
    

    先是getRetriever ,通过getRetriever 来获取RequestManager

    Glide.getRetriever(@Nullable Context context)

     @NonNull
     private static RequestManagerRetriever getRetriever(@Nullable Context context) {
       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();
     }
    

    显示check一下context ,然后通过Glide 获取RequestManagerRetriever

    Glide.get(@NonNull Context context)

    private static volatile Glide glide;
     @NonNull
     public static Glide get(@NonNull Context context) {
       if (glide == null) {
         synchronized (Glide.class) {
           if (glide == null) {
             checkAndInitializeGlide(context);///初始化配置信息
           }
         }
       }
    
       return glide;
     }
    
     private static void checkAndInitializeGlide(@ NonNull 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;
     }
     private static void initializeGlide(@NonNull Context context) {
       initializeGlide(context, new GlideBuilder());
     }  
    
    

    GlideBuilder.build(Context context)

       if (engine == null) {
         engine =
             new Engine(
                 memoryCache,
                 diskCacheFactory,
                 diskCacheExecutor,
                 sourceExecutor,
                 GlideExecutor.newUnlimitedSourceExecutor(),
                 GlideExecutor.newAnimationExecutor(),
                 isActiveResourceRetentionAllowed);
       }
    
       if (defaultRequestListeners == null) {
         defaultRequestListeners = Collections.emptyList();
       } else {
         defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
       }
    
       RequestManagerRetriever requestManagerRetriever =
           new RequestManagerRetriever(requestManagerFactory);
    

    这里的GlideBuilder 初始化了非常多的配置信息,这里我贴了两个比较重要的Engine 和RequestManagerRetriever ,可以看到这些都是伴随着Glide 同时初始化的,也就是整个工程就只有一个,

     @NonNull
     public static RequestManager with(@NonNull Context context) {
       return getRetriever(context).get(context);
     }
    

    现在再看上面的方法大家应该已经知道了getRetriever()方法的大概,如果是第一次调用的话会使用DCL单利模式创建 Glide ,伴随着Glide 的创建同时会初始化一些配置信息比如 : RequestManagerRetriever Engine 等

    RequestManagerRetriever.get(context)

     @NonNull
     public RequestManager get(@NonNull 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);
     }
    

    可以看到如果不是在主线程就使用ApplicationManage,这里我看一下FragmentActivity的分支,他的处理方法比较特殊,具体怎么特殊我们进去看一下,

    RequestManagerRetriever.get(@NonNull FragmentActivity activity)

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

    这里没啥东西,继续往里面走supportFragmentGet

     @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 的方法,同时把自己创建的Fragemnt的 Lifecycle传递给了 RequestManager , 供RequestManager 来监听宿主Activity的状态,来停止请求,这里我们粘贴一些方法

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

    lifecycle.addListener(this); 方法将自身作为参数,就可以监听到状态了,
    我们看看RequestManager在生命周期方法中他都干了什么

     @Override
     public synchronized void onStart() {
       resumeRequests();
       targetTracker.onStart();
     }
    
     /**
      * Lifecycle callback that unregisters for connectivity events (if the
      * android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
      */
     @Override
     public synchronized void onStop() {
       pauseRequests();
       targetTracker.onStop();
     }
    
     /**
      * Lifecycle callback that cancels all in progress requests and clears and recycles resources for
      * all completed requests.
      */
     @Override
     public synchronized void onDestroy() {
       targetTracker.onDestroy();
       for (Target<?> target : targetTracker.getAll()) {
         clear(target);
       }
       targetTracker.clear();
       requestTracker.clearRequests();
       lifecycle.removeListener(this);
       lifecycle.removeListener(connectivityMonitor);
       mainHandler.removeCallbacks(addSelfToLifecycle);
       glide.unregisterRequestManager(this);
     }
    

    在onDestroy 中回收信息,onStart 开始请求,onStop 暂停请求,看到这里我就知道了Glide 是如何与生命周期作为绑定的,

    看到这里我们发现他将RequestManager 放到了SupportRequestManagerFragment 里面,过去看了一下SupportRequestManagerFragment ,他就是一个普通的Fragment,没什么特别的,我们继续看看他是如何得到这个Fragment的,继续看getSupportRequestManagerFragment

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

    看到这里我们恍然大悟,他在FragmentActivity中绑定了一个Fragment,通过这个Fragment来共享改Activity 的RequestManager ,同时可以感知这个Activity 的 声明周期,

    看到了这里已经将Glide.with(context) 看完了,继续看load(String url)

    RequestManager.load(@Nullable String string)

     @NonNull
     @CheckResult
     @Override
     public RequestBuilder<Drawable> load(@Nullable String string) {
       return asDrawable().load(string);
     }
    
     @NonNull
     @CheckResult
     public RequestBuilder<Drawable> asDrawable() {
       return as(Drawable.class);
     }
     @NonNull
     @CheckResult
     public <ResourceType> RequestBuilder<ResourceType> as(
         @NonNull Class<ResourceType> resourceClass) {
       return new RequestBuilder<>(glide, this, resourceClass, context);
     }
    

    可以看到即使我们调用RequestManager.load()方法,他最终还是调用了as 方法来new RequestBuilder,设置其他参数这里就不分析了,继续看RequestBuilder.into(@NonNull ImageView view)

    RequestBuilder.into(@NonNull ImageView view)

     @NonNull
     public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
       Util.assertMainThread();
       Preconditions.checkNotNull(view);
    
       BaseRequestOptions<?> requestOptions = this;
       if (!requestOptions.isTransformationSet()
           && requestOptions.isTransformationAllowed()
           && view.getScaleType() != null) {
         // Clone in this method so that if we use this RequestBuilder to load into a View and then
         // into a different target, we don't retain the transformation applied based on the previous
         // View's scale type.
         switch (view.getScaleType()) {
           case CENTER_CROP:
             requestOptions = requestOptions.clone().optionalCenterCrop();
             break;
           case CENTER_INSIDE:
             requestOptions = requestOptions.clone().optionalCenterInside();
             break;
           case FIT_CENTER:
           case FIT_START:
           case FIT_END:
             requestOptions = requestOptions.clone().optionalFitCenter();
             break;
           case FIT_XY:
             requestOptions = requestOptions.clone().optionalCenterInside();
             break;
           case CENTER:
           case MATRIX:
           default:
             // Do nothing.
         }
       }
    
       return into(
           glideContext.buildImageViewTarget(view, transcodeClass),
           /*targetListener=*/ null,
           requestOptions,
           Executors.mainThreadExecutor());
     }
    

    这里针对ScanType 做了一些配置参数,但是我们使用的是最简单的方法,所以这些参数都没有,直接看下面的into 方法,
    可以看到into方法的第一个参数是通过glideContext ,view ,transcodeClass就是我们使用 load 的时候所调用的as 方法中Drawable,

     @NonNull
     public <X> ViewTarget<ImageView, X> buildImageViewTarget(
         @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
       return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
     }
    

    这里调用了ImageViewTargetFactory 的 buildTarget方法,没有什么特别的,

    ImageViewTargetFactory.buildTarget(@NonNull ImageView view,@NonNull Class<Z> clazz)

    public class ImageViewTargetFactory {
     @NonNull
     @SuppressWarnings("unchecked")
     public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
         @NonNull Class<Z> clazz) {
       if (Bitmap.class.equals(clazz)) {
         return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
       } else if (Drawable.class.isAssignableFrom(clazz)) {
         return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
       } else {
         throw new IllegalArgumentException(
             "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
       }
     }
    }
    

    可以看到如果是Drawable的话返回的就是DrawableImageViewTarget ,回去继续看into 方法

    RequestBuilder <Y extends Target<TranscodeType>> Y into( @NonNull Y target,@Nullable RequestListener<TranscodeType> targetListener,BaseRequestOptions<?> options, Executor callbackExecutor)

     private <Y extends Target<TranscodeType>> Y into(
         @NonNull Y target,
         @Nullable RequestListener<TranscodeType> targetListener,
         BaseRequestOptions<?> options,
         Executor callbackExecutor) {
       Preconditions.checkNotNull(target);
       if (!isModelSet) {
         throw new IllegalArgumentException("You must call #load() before calling #into()");
       }
    
       Request request = buildRequest(target, targetListener, options, callbackExecutor);
    
       Request previous = target.getRequest();
       if (request.isEquivalentTo(previous)
           && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
         request.recycle();
         // If the request is completed, beginning again will ensure the result is re-delivered,
         // triggering RequestListeners and Targets. If the request is failed, beginning again will
         // restart the request, giving it another chance to complete. If the request is already
         // running, we can let it continue running without interruption.
         if (!Preconditions.checkNotNull(previous).isRunning()) {
           // Use the previous request rather than the new one to allow for optimizations like skipping
           // setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
           // that are done in the individual Request.
           previous.begin();
         }
         return target;
       }
    
       requestManager.clear(target);
       target.setRequest(request);
       requestManager.track(target, request);
    
       return target;
     }
    

    看到这里我们终于将请求时候的参数都已经创建完毕了,已经开始创建Request 了,这里看到他首先判断了 isModelSet 这个变量,isModelSet这个变量就是在调用load 方法的时候设置true 的,所以看他抛出异常的文言,在into 方法之前必须先调用load 方法,接下来构建了一个Request

    RequestBuilder buildRequest

     private Request buildRequest(
         Target<TranscodeType> target,
         @Nullable RequestListener<TranscodeType> targetListener,
         BaseRequestOptions<?> requestOptions,
         Executor callbackExecutor) {
       return buildRequestRecursive(
           target,
           targetListener,
           /*parentCoordinator=*/ null,
           transitionOptions,
           requestOptions.getPriority(),
           requestOptions.getOverrideWidth(),
           requestOptions.getOverrideHeight(),
           requestOptions,
           callbackExecutor);
     }
    

    这里获取了RequestBuilder 的OverrideWidth和OverrideHeight,但是我们没有设置,这里应该是默认值,''

    RequestBuilder buildRequestRecursive

    private Request buildRequestRecursive(
         Target<TranscodeType> target,
         @Nullable RequestListener<TranscodeType> targetListener,
         @Nullable RequestCoordinator parentCoordinator,
         TransitionOptions<?, ? super TranscodeType> transitionOptions,
         Priority priority,
         int overrideWidth,
         int overrideHeight,
         BaseRequestOptions<?> requestOptions,
         Executor callbackExecutor) {
    
       // Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
       ErrorRequestCoordinator errorRequestCoordinator = null;
       if (errorBuilder != null) {
         errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
         parentCoordinator = errorRequestCoordinator;
       }
    
       Request mainRequest =
           buildThumbnailRequestRecursive(
               target,
               targetListener,
               parentCoordinator,
               transitionOptions,
               priority,
               overrideWidth,
               overrideHeight,
               requestOptions,
               callbackExecutor);
    
       if (errorRequestCoordinator == null) {
         return mainRequest;
       }
    
       int errorOverrideWidth = errorBuilder.getOverrideWidth();
       int errorOverrideHeight = errorBuilder.getOverrideHeight();
       if (Util.isValidDimensions(overrideWidth, overrideHeight)
           && !errorBuilder.isValidOverride()) {
         errorOverrideWidth = requestOptions.getOverrideWidth();
         errorOverrideHeight = requestOptions.getOverrideHeight();
       }
    
       Request errorRequest =
           errorBuilder.buildRequestRecursive(
               target,
               targetListener,
               errorRequestCoordinator,
               errorBuilder.transitionOptions,
               errorBuilder.getPriority(),
               errorOverrideWidth,
               errorOverrideHeight,
               errorBuilder,
               callbackExecutor);
       errorRequestCoordinator.setRequests(mainRequest, errorRequest);
       return errorRequestCoordinator;
     }
    

    这里我们没有设置erroe的信息, 所以返回的是buildThumbnailRequestRecursive

    RequestBuilder buildThumbnailRequestRecursive

    
     private Request buildThumbnailRequestRecursive(
         Target<TranscodeType> target,
         RequestListener<TranscodeType> targetListener,
         @Nullable RequestCoordinator parentCoordinator,
         TransitionOptions<?, ? super TranscodeType> transitionOptions,
         Priority priority,
         int overrideWidth,
         int overrideHeight,
         BaseRequestOptions<?> requestOptions,
         Executor callbackExecutor) {
       if (thumbnailBuilder != null) {
         // Recursive case: contains a potentially recursive thumbnail request builder.
         if (isThumbnailBuilt) {
           throw new IllegalStateException("You cannot use a request as both the main request and a "
               + "thumbnail, consider using clone() on the request(s) passed to thumbnail()");
         }
    
         TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
             thumbnailBuilder.transitionOptions;
    
         // Apply our transition by default to thumbnail requests but avoid overriding custom options
         // that may have been applied on the thumbnail request explicitly.
         if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
           thumbTransitionOptions = transitionOptions;
         }
    
         Priority thumbPriority = thumbnailBuilder.isPrioritySet()
             ? thumbnailBuilder.getPriority() : getThumbnailPriority(priority);
    
         int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth();
         int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight();
         if (Util.isValidDimensions(overrideWidth, overrideHeight)
             && !thumbnailBuilder.isValidOverride()) {
           thumbOverrideWidth = requestOptions.getOverrideWidth();
           thumbOverrideHeight = requestOptions.getOverrideHeight();
         }
    
         ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
         Request fullRequest =
             obtainRequest(
                 target,
                 targetListener,
                 requestOptions,
                 coordinator,
                 transitionOptions,
                 priority,
                 overrideWidth,
                 overrideHeight,
                 callbackExecutor);
         isThumbnailBuilt = true;
         // Recursively generate thumbnail requests.
         Request thumbRequest =
             thumbnailBuilder.buildRequestRecursive(
                 target,
                 targetListener,
                 coordinator,
                 thumbTransitionOptions,
                 thumbPriority,
                 thumbOverrideWidth,
                 thumbOverrideHeight,
                 thumbnailBuilder,
                 callbackExecutor);
         isThumbnailBuilt = false;
         coordinator.setRequests(fullRequest, thumbRequest);
         return coordinator;
       } else if (thumbSizeMultiplier != null) {
         // Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
         ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
         Request fullRequest =
             obtainRequest(
                 target,
                 targetListener,
                 requestOptions,
                 coordinator,
                 transitionOptions,
                 priority,
                 overrideWidth,
                 overrideHeight,
                 callbackExecutor);
         BaseRequestOptions<?> thumbnailOptions =
             requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);
    
         Request thumbnailRequest =
             obtainRequest(
                 target,
                 targetListener,
                 thumbnailOptions,
                 coordinator,
                 transitionOptions,
                 getThumbnailPriority(priority),
                 overrideWidth,
                 overrideHeight,
                 callbackExecutor);
    
         coordinator.setRequests(fullRequest, thumbnailRequest);
         return coordinator;
       } else {
         // Base case: no thumbnail.
         return obtainRequest(
             target,
             targetListener,
             requestOptions,
             parentCoordinator,
             transitionOptions,
             priority,
             overrideWidth,
             overrideHeight,
             callbackExecutor);
       }
     }
    

    这里没有设置缩略图信息,所以调用的是obtainRequest

    RequestBuilder obtainRequest

     private Request obtainRequest(
         Target<TranscodeType> target,
         RequestListener<TranscodeType> targetListener,
         BaseRequestOptions<?> requestOptions,
         RequestCoordinator requestCoordinator,
         TransitionOptions<?, ? super TranscodeType> transitionOptions,
         Priority priority,
         int overrideWidth,
         int overrideHeight,
         Executor callbackExecutor) {
       return SingleRequest.obtain(
           context,
           glideContext,
           model,
           transcodeClass,
           requestOptions,
           overrideWidth,
           overrideHeight,
           priority,
           target,
           targetListener,
           requestListeners,
           requestCoordinator,
           glideContext.getEngine(),
           transitionOptions.getTransitionFactory(),
           callbackExecutor);
     }
    }
    

    没有逻辑,继续向下看

    SingleRequest obtain

    public static <R> SingleRequest<R> obtain(
         Context context,
         GlideContext glideContext,
         Object model,
         Class<R> transcodeClass,
         BaseRequestOptions<?> requestOptions,
         int overrideWidth,
         int overrideHeight,
         Priority priority,
         Target<R> target,
         RequestListener<R> targetListener,
         @Nullable List<RequestListener<R>> requestListeners,
         RequestCoordinator requestCoordinator,
         Engine engine,
         TransitionFactory<? super R> animationFactory,
         Executor callbackExecutor) {
       @SuppressWarnings("unchecked") SingleRequest<R> request =
           (SingleRequest<R>) POOL.acquire();
       if (request == null) {
         request = new SingleRequest<>();
       }
       request.init(
           context,
           glideContext,
           model,
           transcodeClass,
           requestOptions,
           overrideWidth,
           overrideHeight,
           priority,
           target,
           targetListener,
           requestListeners,
           requestCoordinator,
           engine,
           animationFactory,
           callbackExecutor);
       return request;
     }
    

    看到了obtain 这个方法有没有想起来Handler.obtainMessage 的方法,没错,他们的逻辑都是一样的,使用了一个常量池来保存信息,这样可以节省创建对象的时间,和频繁销毁对象造成的内存抖动
    这里我们看到如果没有设置缩略图信息和error 信息的时候都是创建SingleRequest 实例,我们回头继续看我们没看完的into方法,

    private <Y extends Target<TranscodeType>> Y into(
        @NonNull Y target,
        @Nullable RequestListener<TranscodeType> targetListener,
        BaseRequestOptions<?> options,
        Executor callbackExecutor) {
      Preconditions.checkNotNull(target);
      if (!isModelSet) {
        throw new IllegalArgumentException("You must call #load() before calling #into()");
      }
    
      Request request = buildRequest(target, targetListener, options, callbackExecutor);
    
      Request previous = target.getRequest();
      if (request.isEquivalentTo(previous)
          && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
        request.recycle();
        // If the request is completed, beginning again will ensure the result is re-delivered,
        // triggering RequestListeners and Targets. If the request is failed, beginning again will
        // restart the request, giving it another chance to complete. If the request is already
        // running, we can let it continue running without interruption.
        if (!Preconditions.checkNotNull(previous).isRunning()) {
          // Use the previous request rather than the new one to allow for optimizations like skipping
          // setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
          // that are done in the individual Request.
          previous.begin();
        }
        return target;
      }
    
      requestManager.clear(target);
      target.setRequest(request);
      requestManager.track(target, request);
    
      return target;
    }
    

    这里他将target 和request 绑定了,所以才有target.getRequest(); 和 target.setRequest(request); 这两个方法,既然将他们绑定再来看 target.getRequest();,就知道他是什么意思,也就是获取之前绑定的请求,如果前后两个请求相同,则放弃新创建的请求,直接返回原来已有的请求,继续看看是如何将target 和 request 绑定的

    ViewTarget.setRequest(@Nullable Request request)

     @Override
     public void setRequest(@Nullable Request request) {
       setTag(request);
     }
     private void setTag(@Nullable Object tag) {
       if (tagId == null) {
         isTagUsedAtLeastOnce = true;
         view.setTag(tag);
       } else {
         view.setTag(tagId, tag);
       }
     }
    

    这个绑定就是将这个request 设置为view的tag,
    接下来就应该是请求了requestManager.track(target, request); 就是将这个target 放入已请求的队列里面,同时开始请求

    RequestManager track(@NonNull Target<?> target, @NonNull Request request)

     synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
       targetTracker.track(target);
       requestTracker.runRequest(request);
     }
    

    RequestManager runRequest

     public void runRequest(@NonNull Request request) {
       requests.add(request);
       if (!isPaused) {
         request.begin();
       } else {
         request.clear();
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
           Log.v(TAG, "Paused, delaying request");
         }
         pendingRequests.add(request);
       }
     }
    

    看到了根据一个标识位来判断是否开启请求,这个请求就是根据生命周期判断的,上面我们已经分析过了,这里的调用了request.begin() 方法,我们在上面中创建Request是SingleRequest,去看他的begin方法

    SingleRequest begin

       public synchronized void begin() {
           this.assertNotCallingCallbacks();
           this.stateVerifier.throwIfRecycled();
           this.startTime = LogTime.getLogTime();
           if (this.model == null) {
               if (Util.isValidDimensions(this.overrideWidth, this.overrideHeight)) {
                   this.width = this.overrideWidth;
                   this.height = this.overrideHeight;
               }
    
               int logLevel = this.getFallbackDrawable() == null ? 5 : 3;
               this.onLoadFailed(new GlideException("Received null model"), logLevel);
           } else if (this.status == SingleRequest.Status.RUNNING) {
               throw new IllegalArgumentException("Cannot restart a running request");
           } else if (this.status == SingleRequest.Status.COMPLETE) {
               this.onResourceReady(this.resource, DataSource.MEMORY_CACHE);
           } else {
               this.status = SingleRequest.Status.WAITING_FOR_SIZE;
               if (Util.isValidDimensions(this.overrideWidth, this.overrideHeight)) {
                   this.onSizeReady(this.overrideWidth, this.overrideHeight);
               } else {
                   this.target.getSize(this);
               }
    
               if ((this.status == SingleRequest.Status.RUNNING || this.status == SingleRequest.Status.WAITING_FOR_SIZE) && this.canNotifyStatusChanged()) {
                   this.target.onLoadStarted(this.getPlaceholderDrawable());
               }
    
               if (IS_VERBOSE_LOGGABLE) {
                   this.logV("finished run method in " + LogTime.getElapsedMillis(this.startTime));
               }
    
           }
       }
    

    这里还是判断了一些状态,如果状态是正确的,就会根据我们是否设置了overrideWidth与overrideHeight 来判断走哪一个方法,如果我们设置了,那就是我们已经知道了需要加载的图片大小,如果不知道,就需要调用target 去计算宽高,

    ViewTarget.getSize

    void getSize(@NonNull SizeReadyCallback cb) {
         int currentWidth = getTargetWidth();
         int currentHeight = getTargetHeight();
         if (isViewStateAndSizeValid(currentWidth, currentHeight)) {
           cb.onSizeReady(currentWidth, currentHeight);
           return;
         }
    
         // We want to notify callbacks in the order they were added and we only expect one or two
         // callbacks to be added a time, so a List is a reasonable choice.
         if (!cbs.contains(cb)) {
           cbs.add(cb);
         }
         if (layoutListener == null) {
           ViewTreeObserver observer = view.getViewTreeObserver();
           layoutListener = new SizeDeterminerLayoutListener(this);
           observer.addOnPreDrawListener(layoutListener);
         }
       }
    

    这里需要等待ViewTree 的回调,在成功后会回调request 的onSizeReady 方法将计算后的宽高传入,

    SingleRequest onSizeReady

       public synchronized void onSizeReady(int width, int height) {
           this.stateVerifier.throwIfRecycled();
           if (IS_VERBOSE_LOGGABLE) {
               this.logV("Got onSizeReady in " + LogTime.getElapsedMillis(this.startTime));
           }
    
           if (this.status == SingleRequest.Status.WAITING_FOR_SIZE) {
               this.status = SingleRequest.Status.RUNNING;
               float sizeMultiplier = this.requestOptions.getSizeMultiplier();
               this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
               this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
               if (IS_VERBOSE_LOGGABLE) {
                   this.logV("finished setup for calling load in " + LogTime.getElapsedMillis(this.startTime));
               }
    
               this.loadStatus = this.engine.load(this.glideContext, this.model, this.requestOptions.getSignature(), this.width, this.height, this.requestOptions.getResourceClass(), this.transcodeClass, this.priority, this.requestOptions.getDiskCacheStrategy(), this.requestOptions.getTransformations(), this.requestOptions.isTransformationRequired(), this.requestOptions.isScaleOnlyOrNoTransform(), this.requestOptions.getOptions(), this.requestOptions.isMemoryCacheable(), this.requestOptions.getUseUnlimitedSourceGeneratorsPool(), this.requestOptions.getUseAnimationPool(), this.requestOptions.getOnlyRetrieveFromCache(), this, this.callbackExecutor);
               if (this.status != SingleRequest.Status.RUNNING) {
                   this.loadStatus = null;
               }
    
               if (IS_VERBOSE_LOGGABLE) {
                   this.logV("finished onSizeReady in " + LogTime.getElapsedMillis(this.startTime));
               }
    
           }
       }
    

    看到这里整个加载的过程我们就已经分析完毕了,整个过程还是非常复杂的,但是只要足够耐心还是能看懂的,

    相关文章

      网友评论

        本文标题:Android 进阶学习(十二) Glide源码学习(一) 图片

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