美文网首页js css html
Glide源码分析之加载图片URL

Glide源码分析之加载图片URL

作者: 没有了遇见 | 来源:发表于2022-08-02 16:28 被阅读0次

    简介

    Glide 作为Android开发过程中常见的图片加载工具,在我们日常开发中用到到越来越多.但是个人也只是停留在用的状态.最近时间充裕简单的梳理了一下Glide 加载网络图的流程

    流程

    1.1 Glide.with(content) 得到RequestManagerRetriever初始化了RequestManager和Glide.

     @NonNull
    public static RequestManager with(@NonNull Context context) {
    
     //etRetriever()  获取RequestManagerRetriever
     return getRetriever(context).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);
    }
    
    
    
    Glide.with(context) --> (RequestManagerRetriever)getRetriever(context).get(context)-->
    (RequestManagerRetriever)getApplicationManager(context){
        //初始化 Glide  
      Glide glide = Glide.get(context.getApplicationContext());
      
      //初始化 RequestManager
           applicationManager =
               factory.build(
                   glide,
                   new ApplicationLifecycle(),
                   new EmptyRequestManagerTreeNode(),
                   context.getApplicationContext());
         }
    }
    
    
    //创建 RequestManager
     public interface RequestManagerFactory {
     @NonNull
     RequestManager build(
         @NonNull Glide glide,
         @NonNull Lifecycle lifecycle,
         @NonNull RequestManagerTreeNode requestManagerTreeNode,
         @NonNull Context context);
    }
    //创建 RequestManager
    private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
     @NonNull
     @Override
     public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
         @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
       return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
     }
    };
    }
    
    
    

    1.2 Glide.get(context.getApplicationContext())

    
     Glide.get(context.getApplicationContext()) -->checkAndInitializeGlide(context)
     
    -->initializeGlide(...)-->(GlideBuilder)builder.build(applicationContext)-->
    
    public Glide build(@NonNull Context context) {
         //初始化 Glide
         ...
         
         //注意这个要用 初始化了 下边要用的 (RequestManagerFactory)factory
         RequestManagerRetriever requestManagerRetriever =new RequestManagerRetriever(requestManagerFactory);
         
         return new Glide(.....)
    }
    

    2.0 Glide.with(context).load() 的load方法

    load()方法默认是 asRrawable()类型,用来初始化RequestBuilder 和 loadGeneric()方法初始化model(地址)

    注意
    这里体现了 asBitmap()和asDrawable() 方法必须放在load()前边的原因

    //as方法
    @NonNull
    @CheckResult
    @Override
    public RequestBuilder<Drawable> load(@Nullable String string) {
     return asDrawable().load(string);
    }
    
    @NonNull
    @CheckResult
    public RequestBuilder<Drawable> asDrawable() {
     return as(Drawable.class);
    }
    
    //(重要) 创建了 RequestBuilder  且 默认传入的 resourceClass  是  Drawable.class)
    //返回 获取target DrawableImageViewTarget
     @NonNull
    @CheckResult
    public <ResourceType> RequestBuilder<ResourceType> as(
       @NonNull Class<ResourceType> resourceClass) {
     return new RequestBuilder<>(glide, this, resourceClass, context);
    }
    
    
    
    //设置加载的内容(地址或者资源  )
     /**
    * Sets the specific model to load data for.
    *
    * @param model The model to load data for, or null.
    * @return This request builder.
    */
    @NonNull
    @CheckResult
    @SuppressWarnings("unchecked")
    @Override
    public RequestBuilder<TranscodeType> load(@Nullable Object model) {
     return loadGeneric(model);
    }
    
    @NonNull
    private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
     this.model = model;
     isModelSet = true;
     return this;
    }
    
    
    

    3.Glide 的into() 资源选择以及下载都在这里这里重点分析

    1.调用into方法()

    //调用into()方法
    
      @NonNull
    public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
      Util.assertMainThread();
      Preconditions.checkNotNull(view);
      //设置 RequestOptions 参数
      RequestOptions requestOptions = this.requestOptions;
      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.
        }
      }
          //获取 ViewTarget 类型  默认得到DrawableImageViewTarget  因为load方法默认调用 asDrawable()
          glideContext.buildImageViewTarget(view, transcodeClass)
          
      return into(
          glideContext.buildImageViewTarget(view, transcodeClass),
          /*targetListener=*/ null,
          requestOptions);
    }
    
    //继续调用
      private <Y extends Target<TranscodeType>> Y into(
        @NonNull Y target,
        @Nullable RequestListener<TranscodeType> targetListener,
        @NonNull RequestOptions options) {
        //判断主线程
      Preconditions.checkNotNull(target);
      if (!isModelSet) {
        throw new IllegalArgumentException("You must call #load() before calling #into()");
      }
    
      options = options.autoClone();
      //构建请求  核心方法
      Request request = buildRequest(target, targetListener, options);
    
      Request previous = target.getRequest();
      if (request.isEquivalentTo(previous)
          && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
        request.recycle();
       
        if (!Preconditions.checkNotNull(previous).isRunning()) {
         
          previous.begin();
        }
        return target;
      }
    
      requestManager.clear(target);
      target.setRequest(request);
      requestManager.track(target, request);
    
      return target;
    }
    
    
    

    1.2.构建请求(RequestBuilder 请求构建类)

    //  调用构建请求RequestBuilder 的构建方法
    private Request buildRequest(
        Target<TranscodeType> target,
        @Nullable RequestListener<TranscodeType> targetListener,
        RequestOptions requestOptions) {
      return buildRequestRecursive(
          target,
          targetListener,
          /*parentCoordinator=*/ null,
          transitionOptions,
          requestOptions.getPriority(),
          requestOptions.getOverrideWidth(),
          requestOptions.getOverrideHeight(),
          requestOptions);
    }
    
    private Request buildRequestRecursive(
        Target<TranscodeType> target,
        @Nullable RequestListener<TranscodeType> targetListener,
        @Nullable RequestCoordinator parentCoordinator,
        TransitionOptions<?, ? super TranscodeType> transitionOptions,
        Priority priority,
        int overrideWidth,
        int overrideHeight,
        RequestOptions requestOptions) {
    
      // 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);
    
      if (errorRequestCoordinator == null) {
        return mainRequest;
      }
    
      int errorOverrideWidth = errorBuilder.requestOptions.getOverrideWidth();
      int errorOverrideHeight = errorBuilder.requestOptions.getOverrideHeight();
      if (Util.isValidDimensions(overrideWidth, overrideHeight)
          && !errorBuilder.requestOptions.isValidOverride()) {
        errorOverrideWidth = requestOptions.getOverrideWidth();
        errorOverrideHeight = requestOptions.getOverrideHeight();
      }
    
      Request errorRequest = errorBuilder.buildRequestRecursive(
          target,
          targetListener,
          errorRequestCoordinator,
          errorBuilder.transitionOptions,
          errorBuilder.requestOptions.getPriority(),
          errorOverrideWidth,
          errorOverrideHeight,
          errorBuilder.requestOptions);
      errorRequestCoordinator.setRequests(mainRequest, errorRequest);
      return errorRequestCoordinator;
    }
      
      //执行构建主要的请求 
    private Request buildThumbnailRequestRecursive(
        Target<TranscodeType> target,
        RequestListener<TranscodeType> targetListener,
        @Nullable RequestCoordinator parentCoordinator,
        TransitionOptions<?, ? super TranscodeType> transitionOptions,
        Priority priority,
        int overrideWidth,
        int overrideHeight,
        RequestOptions requestOptions) {
        //第一次为空
      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.requestOptions.isPrioritySet()
            ? thumbnailBuilder.requestOptions.getPriority() : getThumbnailPriority(priority);
    
        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,
                targetListener,
                requestOptions,
                coordinator,
                transitionOptions,
                priority,
                overrideWidth,
                overrideHeight);
        isThumbnailBuilt = true;
        // Recursively generate thumbnail requests.
        Request thumbRequest =
            thumbnailBuilder.buildRequestRecursive(
                target,
                targetListener,
                coordinator,
                thumbTransitionOptions,
                thumbPriority,
                thumbOverrideWidth,
                thumbOverrideHeight,
                thumbnailBuilder.requestOptions);
        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);
        RequestOptions thumbnailOptions = requestOptions.clone()
            .sizeMultiplier(thumbSizeMultiplier);
    
        Request thumbnailRequest =
            obtainRequest(
                target,
                targetListener,
                thumbnailOptions,
                coordinator,
                transitionOptions,
                getThumbnailPriority(priority),
                overrideWidth,
                overrideHeight);
    
        coordinator.setRequests(fullRequest, thumbnailRequest);
        return coordinator;
      } else {
        // Base case: no thumbnail.
        
        // 第一次为空直接执行
        return obtainRequest(
            target,
            targetListener,
            requestOptions,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight);
      }
    }
      //获取请求
    private Request obtainRequest(
        Target<TranscodeType> target,
        RequestListener<TranscodeType> targetListener,
        RequestOptions requestOptions,
        RequestCoordinator requestCoordinator,
        TransitionOptions<?, ? super TranscodeType> transitionOptions,
        Priority priority,
        int overrideWidth,
        int overrideHeight) {
      return SingleRequest.obtain(
          context,
          glideContext,
          model,
          transcodeClass,
          requestOptions,
          overrideWidth,
          overrideHeight,
          priority,
          target,
          targetListener,
          requestListener,
          requestCoordinator,
          glideContext.getEngine(),
          transitionOptions.getTransitionFactory());
    }
    
    
    // SingleRequest 单例请求类
    
    
      public static <R> SingleRequest<R> obtain(
        Context context,
        GlideContext glideContext,
        Object model,
        Class<R> transcodeClass,
        RequestOptions requestOptions,
        int overrideWidth,
        int overrideHeight,
        Priority priority,
        Target<R> target,
        RequestListener<R> targetListener,
        RequestListener<R> requestListener,
        RequestCoordinator requestCoordinator,
        Engine engine,
        TransitionFactory<? super R> animationFactory) {
      @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,
          requestListener,
          requestCoordinator,
          engine,
          animationFactory);
      return request;
    }
    
    //初始化单例 请求
    rivate void init(
        Context context,
        GlideContext glideContext,
        Object model,
        Class<R> transcodeClass,
        RequestOptions requestOptions,
        int overrideWidth,
        int overrideHeight,
        Priority priority,
        Target<R> target,
        RequestListener<R> targetListener,
        RequestListener<R> requestListener,
        RequestCoordinator requestCoordinator,
        Engine engine,
        TransitionFactory<? super R> animationFactory) {
      this.context = context;
      this.glideContext = glideContext;
      this.model = model;
      this.transcodeClass = transcodeClass;
      this.requestOptions = requestOptions;
      this.overrideWidth = overrideWidth;
      this.overrideHeight = overrideHeight;
      this.priority = priority;
      this.target = target;
      this.targetListener = targetListener;
      this.requestListener = requestListener;
      this.requestCoordinator = requestCoordinator;
      this.engine = engine;
      this.animationFactory = animationFactory;
      status = Status.PENDING;
    }
    
    

    1.3 开启请求

    
    
      private <Y extends Target<TranscodeType>> Y into(
        @NonNull Y target,
        @Nullable RequestListener<TranscodeType> targetListener,
        @NonNull RequestOptions options) {
        //判断主线程
      Preconditions.checkNotNull(target);
      if (!isModelSet) {
        throw new IllegalArgumentException("You must call #load() before calling #into()");
      }
    
      options = options.autoClone();
      //构建请求  只是做了个初始化的操作  
      Request request = buildRequest(target, targetListener, options);
         //  返回这个Target 上边的请求  因为上边是做初始化操作所以 第一次这个previous 请求是null
         //  request.isEquivalentTo(previous)  =false
      Request previous = target.getRequest();
      if (request.isEquivalentTo(previous)
          && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
        request.recycle();
       
        if (!Preconditions.checkNotNull(previous).isRunning()) {
         //开启请求
          previous.begin();
        }
        return target;
      }
    
      requestManager.clear(target);
      //给target设置上请求
      target.setRequest(request);
      //开启 请求(正常情况下走这个)
      requestManager.track(target, request);
    
      return target;
    }
    
    
      void track(Target<?> target, Request request) {
      targetTracker.track(target);
      requestTracker.runRequest(request);
    }
    
    
    public void runRequest(Request request) {
      requests.add(request);
      // 我的Demo是在 Activity 中展示所以isPaused()是true 所以是否执行请求是根据生命周期走的
      
      if (!isPaused) {
        request.begin();
      } else {
        pendingRequests.add(request);
      }
    }
    
    
    查了一下代码 因为  RequestManager 实现了 LifecycleListener 监听了页面的生命周期 所以 
    
    RequestManager中实现了 onStart 方法 resumeRequests 调用了resumeRequests()
    @Override
    public void onStart() {
      resumeRequests();
      targetTracker.onStart();
    }
    
    
     //页面展示开启请求
    public void resumeRequests() {
      isPaused = false;
      for (Request request : Util.getSnapshot(requests)) {
        if (!request.isComplete() && !request.isCancelled() && !request.isRunning()) {
          request.begin();
        }
      }
      pendingRequests.clear();
    }
    
    //上边是请求执行了
    
    

    1.4 SingleRequest 单例请求的代码

    
    public static <R> SingleRequest<R> obtain(
        Context context,
        GlideContext glideContext,
        Object model,
        Class<R> transcodeClass,
        RequestOptions requestOptions,
        int overrideWidth,
        int overrideHeight,
        Priority priority,
        Target<R> target,
        RequestListener<R> targetListener,
        RequestListener<R> requestListener,
        RequestCoordinator requestCoordinator,
        Engine engine,
        TransitionFactory<? super R> animationFactory) {
      @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,
          requestListener,
          requestCoordinator,
          engine,
          animationFactory);
      return request;
    }
    
    @SuppressWarnings("WeakerAccess")
    @Synthetic
    SingleRequest() {
      // just create, instances are reused with recycle/init
    }
    //初始化了请求的数据
    private void init(
        Context context,
        GlideContext glideContext,
        Object model,
        Class<R> transcodeClass,
        RequestOptions requestOptions,
        int overrideWidth,
        int overrideHeight,
        Priority priority,
        Target<R> target,
        RequestListener<R> targetListener,
        RequestListener<R> requestListener,
        RequestCoordinator requestCoordinator,
        Engine engine,
        TransitionFactory<? super R> animationFactory) {
      this.context = context;
      this.glideContext = glideContext;
      this.model = model;
      this.transcodeClass = transcodeClass;
      this.requestOptions = requestOptions;
      this.overrideWidth = overrideWidth;
      this.overrideHeight = overrideHeight;
      this.priority = priority;
      this.target = target;
      this.targetListener = targetListener;
      this.requestListener = requestListener;
      this.requestCoordinator = requestCoordinator;
      this.engine = engine;
      this.animationFactory = animationFactory;
      status = Status.PENDING;
    }
    
    
    //开启了请求
      @Override
    public void begin() {
      assertNotCallingCallbacks();
      stateVerifier.throwIfRecycled();
      startTime = LogTime.getLogTime();
      // model 就是load() 传入的地址或者资源数据 为空直接走了 错误的回调然后直接返回
      if (model == null) {
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
          width = overrideWidth;
          height = overrideHeight;
        }
        
        onLoadFailed(new GlideException("Received null model"), logLevel);
        return;
      }
    
      if (status == Status.RUNNING) {
        throw new IllegalArgumentException("Cannot restart a running request");
      }
    
      //加载完成状态
      if (status == Status.COMPLETE) {
        onResourceReady(resource, DataSource.MEMORY_CACHE);
        return;
      }
    
      // Restarts for requests that are neither complete nor running can be treated as new requests
      // and can run again from the beginning.
    
      status = Status.WAITING_FOR_SIZE;
      // 判断图片的宽高  有宽高证明存在直接展示
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        onSizeReady(overrideWidth, overrideHeight);
      } else {
      //重要 执行了获取宽高的方法  因为实现了SizeReadyCallback接口 执行  onSizeReady() 方法
      
      //DrawableImageViewTarget --> ViewTarget --> getSize(SizeReadyCallback cb)
           //{      cb.onSizeReady(currentWidth, currentHeight);}
          
      target.getSize(this);
      }
    
      if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
          && canNotifyStatusChanged()) {
          //开始加载  getPlaceholderDrawable() 获取占位图
        target.onLoadStarted(getPlaceholderDrawable());
      }
      if (IS_VERBOSE_LOGGABLE) {
        logV("finished run method in " + LogTime.getElapsedMillis(startTime));
      }
    }
    
    
    

    1.5 Engine 下载图片

    
      @Override
    public void onSizeReady(int width, int height) {
      stateVerifier.throwIfRecycled();
      if (IS_VERBOSE_LOGGABLE) {
        logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
      if (status != Status.WAITING_FOR_SIZE) {
        return;
      }
      status = Status.RUNNING;
    
      float sizeMultiplier = requestOptions.getSizeMultiplier();
      this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
      this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
    
      if (IS_VERBOSE_LOGGABLE) {
        logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
      }
      
     //  Engine  负责启动负载并管理活动和缓存的资源 
     // 加载资源     监听是 ResourceCallback  实现方法 onResourceReady  加载准备
      loadStatus = engine.load(
          glideContext,
          model,
          requestOptions.getSignature(),
          this.width,
          this.height,
          requestOptions.getResourceClass(),
          transcodeClass,
          priority,
          requestOptions.getDiskCacheStrategy(),
          requestOptions.getTransformations(),
          requestOptions.isTransformationRequired(),
          requestOptions.isScaleOnlyOrNoTransform(),
          requestOptions.getOptions(),
          requestOptions.isMemoryCacheable(),
          requestOptions.getUseUnlimitedSourceGeneratorsPool(),
          requestOptions.getUseAnimationPool(),
          requestOptions.getOnlyRetrieveFromCache(),
          this);
    
      // This is a hack that's only useful for testing right now where loads complete synchronously
      // even though under any executor running on any thread but the main thread, the load would
      // have completed asynchronously.
      if (status != Status.RUNNING) {
        loadStatus = null;
      }
      if (IS_VERBOSE_LOGGABLE) {
        logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
    
    
    //  Engine  负责启动负载并管理活动和缓存的资源
    
      public <R> LoadStatus load(
        GlideContext glideContext,
        Object model,
        Key signature,
        int width,
        int height,
        Class<?> resourceClass,
        Class<R> transcodeClass,
        Priority priority,
        DiskCacheStrategy diskCacheStrategy,
        Map<Class<?>, Transformation<?>> transformations,
        boolean isTransformationRequired,
        boolean isScaleOnlyOrNoTransform,
        Options options,
        boolean isMemoryCacheable,
        boolean useUnlimitedSourceExecutorPool,
        boolean useAnimationPool,
        boolean onlyRetrieveFromCache,
        ResourceCallback cb) {
      Util.assertMainThread();
      long startTime = LogTime.getLogTime();
    
      EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
          resourceClass, transcodeClass, options);
      //从活动资源加载资源
      EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
      if (active != null) {
        cb.onResourceReady(active, DataSource.MEMORY_CACHE);
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
          logWithTimeAndKey("Loaded resource from active resources", startTime, key);
        }
        return null;
      }
    //加载缓存资源
      EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
      if (cached != null) {
        cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
          logWithTimeAndKey("Loaded resource from cache", startTime, key);
        }
        return null;
      }
      //当前加载网络资源 (同请求加载重新请求的资源))
      EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
      if (current != null) {
        current.addCallback(cb);
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
          logWithTimeAndKey("Added to existing load", startTime, key);
        }
        return new LoadStatus(cb, current);
      }
    
      EngineJob<R> engineJob =
          engineJobFactory.build(
              key,
              isMemoryCacheable,
              useUnlimitedSourceExecutorPool,
              useAnimationPool,
              onlyRetrieveFromCache);
    
      DecodeJob<R> decodeJob =
          decodeJobFactory.build(
              glideContext,
              model,
              key,
              signature,
              width,
              height,
              resourceClass,
              transcodeClass,
              priority,
              diskCacheStrategy,
              transformations,
              isTransformationRequired,
              isScaleOnlyOrNoTransform,
              onlyRetrieveFromCache,
              options,
              engineJob);
    
      jobs.put(key, engineJob);
          //增加监听
      engineJob.addCallback(cb);
      //启动加载
      engineJob.start(decodeJob);
    
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Started new load", startTime, key);
      }
      return new LoadStatus(cb, engineJob);
    }
    // 开启异步加载数据
      public void start(DecodeJob<R> decodeJob) {
      this.decodeJob = decodeJob;
      GlideExecutor executor = decodeJob.willDecodeFromCache()
          ? diskCacheExecutor
          : getActiveSourceExecutor();
          //开始加载
      executor.execute(decodeJob);
    }
     
    
    
    

    1.6 DecodeJob下载的线程(重要)

     @Override
    public void run() {
    
      TraceCompat.beginSection("DecodeJob#run");
      
      DataFetcher<?> localFetcher = currentFetcher;
      try {
      //是否取消请求
        if (isCancelled) {
          notifyFailed();
          return;
        }
        //运行
        runWrapped();
      } catch (Throwable t) {
        // Catch Throwable and not Exception to handle OOMs. Throwables are swallowed by our
        // usage of .submit() in GlideExecutor so we're not silently hiding crashes by doing this. We
        // are however ensuring that our callbacks are always notified when a load fails. Without this
        // notification, uncaught throwables never notify the corresponding callbacks, which can cause
        // loads to silently hang forever, a case that's especially bad for users using Futures on
        // background threads.
        if (Log.isLoggable(TAG, Log.DEBUG)) {
          Log.d(TAG, "DecodeJob threw unexpectedly"
              + ", isCancelled: " + isCancelled
              + ", stage: " + stage, t);
        }
        // When we're encoding we've already notified our callback and it isn't safe to do so again.
        if (stage != Stage.ENCODE) {
          throwables.add(t);
          notifyFailed();
        }
        if (!isCancelled) {
          throw t;
        }
      } finally {
        // Keeping track of the fetcher here and calling cleanup is excessively paranoid, we call
        // close in all cases anyway.
        if (localFetcher != null) {
          localFetcher.cleanup();
        }
        TraceCompat.endSection();
      }
    }
      //运行选择的处理()会循环执行 去判断三级资源 先资源判断 再缓存半段 再下载
    private void runWrapped() {
       switch (runReason) {
       // The first time we've been submitted.  第一次请求
        case INITIALIZE:
             //获取资源的类型(初始阶段)
          stage = getNextStage(Stage.INITIALIZE);
             //获取一个资源生成器
          currentGenerator = getNextGenerator();
          runGenerators();
          break;
          //从缓存处理
        case SWITCH_TO_SOURCE_SERVICE:
          runGenerators();
          break;
          //我们在一个我们不拥有的线程上检索了一些数据,并希望切换回我们的线程
        case DECODE_DATA:
          decodeFromRetrievedData();
          break;
        default:
          throw new IllegalStateException("Unrecognized run reason: " + runReason);
      }
    }
      //判断资源的类型  缓存 还是资源文件
    private DataFetcherGenerator getNextGenerator() {
      switch (stage) {
        case RESOURCE_CACHE:
          return new ResourceCacheGenerator(decodeHelper, this);
        case DATA_CACHE:
          return new DataCacheGenerator(decodeHelper, this);
        case SOURCE:
        //下载走这里
          return new SourceGenerator(decodeHelper, this);
        case FINISHED:
          return null;
        default:
          throw new IllegalStateException("Unrecognized stage: " + stage);
      }
    }
    
    //执行 数据判断(会循环上掉直到找到数据)  HttpUrlFetcher  没缓存走下载  
      private void runGenerators() {
      currentThread = Thread.currentThread();
      startFetchTime = LogTime.getLogTime();
      boolean isStarted = false;
      //currentGenerator.startNext() 执行找数据
      while (!isCancelled && currentGenerator != null
          && !(isStarted = currentGenerator.startNext())) {
        stage = getNextStage(stage);
        currentGenerator = getNextGenerator();
    
        if (stage == Stage.SOURCE) {
          reschedule();
          return;
        }
      }
      // We've run out of stages and generators, give up.
      if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
        notifyFailed();
      }
    
      // Otherwise a generator started a new load and we expect to be called back in
      // onDataFetcherReady.
    }
    
      @Override
    public boolean startNext() {
      if (dataToCache != null) {
        Object data = dataToCache;
        dataToCache = null;
        cacheData(data);
      }
    
      if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
        return true;
      }
      sourceCacheGenerator = null;
    
      loadData = null;
      boolean started = false;
      while (!started && hasNextModelLoader()) {
        loadData = helper.getLoadData().get(loadDataListIndex++);
        if (loadData != null
            && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
            || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
          started = true;
          loadData.fetcher.loadData(helper.getPriority(), this);
        }
      }
      return started;
    }
    
    
    
    
    

    1.7 下载\

    
      //HttpUrlFetcher 
       //* A DataFetcher that retrieves an {@link java.io.InputStream} for a Url.
    
    
    
     @Override
      public boolean startNext() {
        if (dataToCache != null) {
          Object data = dataToCache;
          dataToCache = null;
          cacheData(data);
        }
    
        if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
          return true;
        }
        sourceCacheGenerator = null;
    
        loadData = null;
        boolean started = false;
        while (!started && hasNextModelLoader()) {
          loadData = helper.getLoadData().get(loadDataListIndex++);
          if (loadData != null
              && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
              || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
            started = true;
            loadData.fetcher.loadData(helper.getPriority(), this);
          }
        }
        return started;
      }
      
      
      //  图片下载
      
      
      @Override
      public void loadData(@NonNull Priority priority,
          @NonNull DataCallback<? super InputStream> callback) {
        long startTime = LogTime.getLogTime();
        try {
     // callback SourceGenerator 实现了  DataFetcher.DataCallback<Object> 接口  回调到 SourceGenerator
        
          InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
          callback.onDataReady(result);
        } catch (IOException e) {
          if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Failed to load data for url", e);
          }
          //FetcherReadyCallback  下载回调
          callback.onLoadFailed(e);
        } finally {
          if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
          }
        }
      }
    
      private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
          Map<String, String> headers) throws IOException {
        if (redirects >= MAXIMUM_REDIRECTS) {
          throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
        } else {
          // Comparing the URLs using .equals performs additional network I/O and is generally broken.
          // See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
          try {
            if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
              throw new HttpException("In re-direct loop");
    
            }
          } catch (URISyntaxException e) {
            // Do nothing, this is best effort.
          }
        }
    
        urlConnection = connectionFactory.build(url);
        for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
          urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
        }
        urlConnection.setConnectTimeout(timeout);
        urlConnection.setReadTimeout(timeout);
        urlConnection.setUseCaches(false);
        urlConnection.setDoInput(true);
    
        // Stop the urlConnection instance of HttpUrlConnection from following redirects so that
        // redirects will be handled by recursive calls to this method, loadDataWithRedirects.
        urlConnection.setInstanceFollowRedirects(false);
    
        // Connect explicitly to avoid errors in decoders if connection fails.
        urlConnection.connect();
        // Set the stream so that it's closed in cleanup to avoid resource leaks. See #2352.
        stream = urlConnection.getInputStream();
        if (isCancelled) {
          return null;
        }
        final int statusCode = urlConnection.getResponseCode();
        if (isHttpOk(statusCode)) {
          return getStreamForSuccessfulRequest(urlConnection);
        } else if (isHttpRedirect(statusCode)) {
          String redirectUrlString = urlConnection.getHeaderField("Location");
          if (TextUtils.isEmpty(redirectUrlString)) {
            throw new HttpException("Received empty or null redirect url");
          }
          URL redirectUrl = new URL(url, redirectUrlString);
          // Closing the stream specifically is required to avoid leaking ResponseBodys in addition
          // to disconnecting the url connection below. See #2352.
          cleanup();
          return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
        } else if (statusCode == INVALID_STATUS_CODE) {
          throw new HttpException(statusCode);
        } else {
          throw new HttpException(urlConnection.getResponseMessage(), statusCode);
        }
      }
      
    

    1.8 回调

        // 的回调到  SourceGenerator  onDataReady
      @Override
      public void onDataReady(Object data) {
        DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
        if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
          dataToCache = data;
          // We might be being called back on someone else's thread. Before doing anything, we should
          // reschedule to get back onto Glide's thread.
          cb.reschedule();
        } else {
          cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
              loadData.fetcher.getDataSource(), originalKey);
        }
      }
      
      
      
      
       // 因为  DecodeJob 实现了   FetcherReadyCallback 接口 且 SourceGenerator(this)  是这么创建的 
     //所以回调到 DecodeJob  的  onDataFetcherReady方法
    
        @Override
      public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
          DataSource dataSource, Key attemptedKey) {
        // This data fetcher will be loading from a File and provide the wrong data source, so override
        // with the data source of the original fetcher
        // cb  是 DecodeJob
        cb.onDataFetcherReady(sourceKey, data, fetcher, loadData.fetcher.getDataSource(), sourceKey);
      }
      
    
        //  DecodeJob  的 onDataFetcherReady
        @Override
      public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
          DataSource dataSource, Key attemptedKey) {
        this.currentSourceKey = sourceKey;
        this.currentData = data;
        this.currentFetcher = fetcher;
        this.currentDataSource = dataSource;
        this.currentAttemptingKey = attemptedKey;
        if (Thread.currentThread() != currentThread) {
          runReason = RunReason.DECODE_DATA;
          callback.reschedule(this);
        } else {
          TraceCompat.beginSection("DecodeJob.decodeFromRetrievedData");
          try {
          //数解码(处理下载的数据)
            decodeFromRetrievedData();
          } finally {
            TraceCompat.endSection();
          }
        }
      }
      
      
        private void decodeFromRetrievedData() {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
          logWithTimeAndKey("Retrieved data", startFetchTime,
              "data: " + currentData
              + ", cache key: " + currentSourceKey
              + ", fetcher: " + currentFetcher);
        }
        Resource<R> resource = null;
        try {
          resource = decodeFromData(currentFetcher, currentData, currentDataSource);
        } catch (GlideException e) {
          e.setLoggingDetails(currentAttemptingKey, currentDataSource);
          throwables.add(e);
        }
        if (resource != null) {
          notifyEncodeAndRelease(resource, currentDataSource);
        } else {
          runGenerators();
        }
      }
      
      //通知
      private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
        if (resource instanceof Initializable) {
          ((Initializable) resource).initialize();
        }
    
        Resource<R> result = resource;
        LockedResource<R> lockedResource = null;
        if (deferredEncodeManager.hasResourceToEncode()) {
          lockedResource = LockedResource.obtain(resource);
          result = lockedResource;
        }
         //下载完成通知填充页面
        notifyComplete(result, dataSource);
    
        stage = Stage.ENCODE;
        try {
          if (deferredEncodeManager.hasResourceToEncode()) {
            deferredEncodeManager.encode(diskCacheProvider, options);
          }
        } finally {
          if (lockedResource != null) {
            lockedResource.unlock();
          }
        }
        // Call onEncodeComplete outside the finally block so that it's not called if the encode process
        // throws.
        onEncodeComplete();
      }
      
      
      private void notifyComplete(Resource<R> resource, DataSource dataSource) {
        setNotifiedOrThrow();
        
       // callback 是传入的调用EngineJob  调用 EngineJob的onResourceReady方法  
        callback.onResourceReady(resource, dataSource);
      }
    
    
    
    //EngineJob的onResourceReady()方法
    //发完成的通知
      @Override
      public void onResourceReady(Resource<R> resource, DataSource dataSource) {
        this.resource = resource;
        this.dataSource = dataSource;
        MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
      }
    
    //状态的Handler 
    
    private static final Handler MAIN_THREAD_HANDLER =
          new Handler(Looper.getMainLooper(), new MainThreadCallback());
      
      
      private static class MainThreadCallback implements Handler.Callback {
    
        @Synthetic
        @SuppressWarnings("WeakerAccess")
        MainThreadCallback() { }
    
        @Override
        public boolean handleMessage(Message message) {
          EngineJob<?> job = (EngineJob<?>) message.obj;
          switch (message.what) {
            case MSG_COMPLETE:
            //完成的的通知
              job.handleResultOnMainThread();
              break;
            case MSG_EXCEPTION:
              job.handleExceptionOnMainThread();
              break;
            case MSG_CANCELLED:
              job.handleCancelledOnMainThread();
              break;
            default:
              throw new IllegalStateException("Unrecognized message: " + message.what);
          }
          return true;
        }
      }
      
      
      
      
        @Synthetic
      void handleResultOnMainThread() {
        stateVerifier.throwIfRecycled();
        if (isCancelled) {
          resource.recycle();
          release(false /*isRemovedFromQueue*/);
          return;
        } else if (cbs.isEmpty()) {
          throw new IllegalStateException("Received a resource without any callbacks to notify");
        } else if (hasResource) {
          throw new IllegalStateException("Already have resource");
        }
        engineResource = engineResourceFactory.build(resource, isCacheable);
        hasResource = true;
    
        // Hold on to resource for duration of request so we don't recycle it in the middle of
        // notifying if it synchronously released by one of the callbacks.
        engineResource.acquire();
        listener.onEngineJobComplete(this, key, engineResource);
    
        //noinspection ForLoopReplaceableByForEach to improve perf
        for (int i = 0, size = cbs.size(); i < size; i++) {
          ResourceCallback cb = cbs.get(i);
          if (!isInIgnoredCallbacks(cb)) {
            engineResource.acquire();
            //cb是 SingleRequest    回调的单例请求onResourceReady 的方法
            cb.onResourceReady(engineResource, dataSource);
          }
        }
        // Our request is complete, so we can release the resource.
        engineResource.release();
    
        release(false /*isRemovedFromQueue*/);
      }
      
      // SingleRequest 单例请求
      
        /**
       * A callback method that should never be invoked directly.
       */
      @SuppressWarnings("unchecked")
      @Override
      public void onResourceReady(Resource<?> resource, DataSource dataSource) {
        stateVerifier.throwIfRecycled();
        loadStatus = null;
        if (resource == null) {
          GlideException exception = new GlideException("Expected to receive a Resource<R> with an "
              + "object of " + transcodeClass + " inside, but instead got null.");
          onLoadFailed(exception);
          return;
        }
    
        Object received = resource.get();
        if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
          releaseResource(resource);
          GlideException exception = new GlideException("Expected to receive an object of "
              + transcodeClass + " but instead" + " got "
              + (received != null ? received.getClass() : "") + "{" + received + "} inside" + " "
              + "Resource{" + resource + "}."
              + (received != null ? "" : " " + "To indicate failure return a null Resource "
              + "object, rather than a Resource object containing null data."));
          onLoadFailed(exception);
          return;
        }
    
        if (!canSetResource()) {
          releaseResource(resource);
          // We can't put the status to complete before asking canSetResource().
          status = Status.COMPLETE;
          return;
        }
        //资源准备好了 
        onResourceReady((Resource<R>) resource, (R) received, dataSource);
      }
    
      /**
       * Internal {@link #onResourceReady(Resource, DataSource)} where arguments are known to be safe.
       *
       * @param resource original {@link Resource}, never <code>null</code>
       * @param result   object returned by {@link Resource#get()}, checked for type and never
       *                 <code>null</code>
       */
      private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
        // We must call isFirstReadyResource before setting status.
        boolean isFirstResource = isFirstReadyResource();
        status = Status.COMPLETE;
        this.resource = resource;
    
        if (glideContext.getLogLevel() <= Log.DEBUG) {
          Log.d(GLIDE_TAG, "Finished loading " + result.getClass().getSimpleName() + " from "
              + dataSource + " for " + model + " with size [" + width + "x" + height + "] in "
              + LogTime.getElapsedMillis(startTime) + " ms");
        }
    
        isCallingCallbacks = true;
        try {
          if ((requestListener == null
              || !requestListener.onResourceReady(result, model, target, dataSource, isFirstResource))
              && (targetListener == null
              || !targetListener.onResourceReady(result, model, target, dataSource, isFirstResource))) {
            Transition<? super R> animation =
                animationFactory.build(dataSource, isFirstResource);
                //填充到页面 target 默认是DrawableImageViewTarget
            target.onResourceReady(result, animation);
          }
        } finally {
          isCallingCallbacks = false;
        }
    
        notifyLoadSuccess();
      }
      
      //最后回调到DrawableImageViewTarget 的setResource() 方法  view是个ImagView
       @Override
      protected void setResource(@Nullable Drawable resource) {
        view.setImageDrawable(resource);
      }
    
      
      
    

    总结

    这里简单的梳理了Glide 第一次加载图片 从初始化到配置参数,然后判断是否有缓存再到下载完成然后通知展示的简单流程.源码中涉及到的回调比较多建议代码跟一下(特别注意生命周期的影响).

    大致上代码流程是:
    Glide.with()配置Glide 的一些参数 load() 配置请求的构建起 into()首先判断本子资源是否有然后缓存文件是否存在都没有就调用下载,下载完成通知展示.因为Glide RequestManager implements LifecycleListener 监听了页面的生命周期注意,一下生命周期对展示的影响

    还有一些生命周期对Glide的影响,以及异常展示的流程没有处理,有兴趣的可以研究下

    相关文章

      网友评论

        本文标题:Glide源码分析之加载图片URL

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