2019-11-19Glide 源碼流程分析<1>

注:這是基于4.10.0的源碼
先上一張時(shí)序圖:


Glide-時(shí)序圖.png

先來(lái)看glide使用

        Glide.with(this)
            .load("http://goo.gl/gEgYUd")
            .into(iv_test)

into 之前主要是做一些初始化操作,構(gòu)建單例的Glide躲雅,創(chuàng)建空的fragment來(lái)感知生命周期,這里就不做介紹來(lái)看into之后做了什么

  @NonNull
  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    //檢查線程
    Util.assertMainThread();
    //判斷null
    Preconditions.checkNotNull(view);
    //判斷view自身是否設(shè)置了ScaleType
    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.
      }
    }
    //調(diào)用into方法
     //注意第一個(gè)參數(shù),返回的是一個(gè)DrawableImageViewTarget對(duì)象
    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        Executors.mainThreadExecutor());
  }

  @NonNull
  @Synthetic
  <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      Executor callbackExecutor) {
    //繼續(xù)調(diào)用自身
    return into(target, targetListener, /*options=*/ this, 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()");
    }
    //構(gòu)建一個(gè)請(qǐng)求
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
    //從target中獲取請(qǐng)求
    Request previous = target.getRequest();
     //請(qǐng)求是同一個(gè)
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      if (!Preconditions.checkNotNull(previous).isRunning()) {
       //開啟請(qǐng)求
        previous.begin();
      }
      return target;
    }
    //不是同一個(gè),清除
    requestManager.clear(target);
    //將請(qǐng)求設(shè)置到target
    target.setRequest(request);
    //添加到requestManager中貌夕,并開啟請(qǐng)求,也就是request.begin方法
    //就是這一個(gè)民镜,將請(qǐng)求綁定生命周期
    requestManager.track(target, request);
    return target;
  }

通過上面可以知道啡专,主要就是構(gòu)建一個(gè)request,然后調(diào)用begin方法制圈,下面看如何構(gòu)建請(qǐng)求

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

  private Request buildRequestRecursive(
      Object requestLock,
      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;
    //默認(rèn)為null
    if (errorBuilder != null) {
      errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator);
      parentCoordinator = errorRequestCoordinator;
    }

    Request mainRequest =
        buildThumbnailRequestRecursive(
            requestLock,
            target,
            targetListener,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight,
            requestOptions,
            callbackExecutor);

 //....
  }

  private Request buildThumbnailRequestRecursive(
      Object requestLock,
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {
    //....
      //假設(shè)沒有做任何的操作们童,則直接返回這個(gè)
      return obtainRequest(
          requestLock,
          target,
          targetListener,
          requestOptions,
          parentCoordinator,
          transitionOptions,
          priority,
          overrideWidth,
          overrideHeight,
          callbackExecutor);
    }
  }

先假設(shè)沒有配置縮略圖什么的,所以直接返回的就是obtainRequest()方法返回的

  private Request obtainRequest(
      Object requestLock,
      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,
        requestLock,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }

  public static <R> SingleRequest<R> obtain(
      Context context,
      GlideContext glideContext,
      Object requestLock,
      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) {
    return new SingleRequest<>(
        context,
        glideContext,
        requestLock,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        engine,
        animationFactory,
        callbackExecutor);
  }

所以這個(gè)request就是一個(gè)SingleRequest對(duì)象鲸鹦,進(jìn)入SingleRequest中的begin方法

  @Override
  public void begin() {
    synchronized (requestLock) {
      assertNotCallingCallbacks();
      stateVerifier.throwIfRecycled();
      startTime = LogTime.getLogTime();
      //判斷model是否賦值慧库,注意這個(gè)model是我們調(diào)用load()中傳進(jìn)來(lái)的
      //這里傳進(jìn)來(lái)的是一個(gè)string類型的地址
      if (model == null) {
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
          width = overrideWidth;
          height = overrideHeight;
        }
        // Only log at more verbose log levels if the user has set a fallback drawable, because
        // fallback Drawables indicate the user expects null models occasionally.
        int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
        //調(diào)用失敗方法
        onLoadFailed(new GlideException("Received null model"), logLevel);
        return;
      }
      //如果已經(jīng)在運(yùn)行,拋出異常
      if (status == Status.RUNNING) {
        throw new IllegalArgumentException("Cannot restart a running request");
      }

      //如果已經(jīng)完成馋嗜,調(diào)用onResourceReady
      if (status == Status.COMPLETE) {
        onResourceReady(resource, DataSource.MEMORY_CACHE);
        return;
      }

      // 將狀態(tài)至為獲取尺寸
      status = Status.WAITING_FOR_SIZE;
      //如果尺寸可用齐板,調(diào)用onSizeReady方法
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        onSizeReady(overrideWidth, overrideHeight);
      } else {
        //調(diào)用獲取尺寸,最后會(huì)回調(diào)到onSizeReady方法
        target.getSize(this);
      }

      if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
          && canNotifyStatusChanged()) {
        target.onLoadStarted(getPlaceholderDrawable());
      }
      if (IS_VERBOSE_LOGGABLE) {
        logV("finished run method in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }

不過尺寸是否可用葛菇,在的到尺寸之后都會(huì)回調(diào)到onSizeReady()方法

  @Override
  public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    synchronized (requestLock) {
      if (IS_VERBOSE_LOGGABLE) {
        logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
      //如果不是獲取尺寸回調(diào)甘磨,返回
      if (status != Status.WAITING_FOR_SIZE) {
        return;
      }
      //將狀態(tài)至為運(yùn)行匯總
      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));
      }
      //調(diào)用load,獲取
      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,
              callbackExecutor);

  //....
    }
  }

走到了engine.load方法

  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,
      Executor callbackExecutor) {
    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
    //構(gòu)建一個(gè)key
    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);

    EngineResource<?> memoryResource;
    synchronized (this) {
      //從內(nèi)存中獲取
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);

      if (memoryResource == null) {
        //內(nèi)存中沒有獲取到眯停,嘗試從本地或者網(wǎng)絡(luò)中獲取
        return waitForExistingOrStartNewJob(
            glideContext,
            model,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            options,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache,
            cb,
            callbackExecutor,
            key,
            startTime);
      }
    }

    //內(nèi)存中獲取成功济舆,回調(diào)出去
    cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
    return null;
  }

loadFromMemory()方法就是從內(nèi)存中獲取資源,默認(rèn)在內(nèi)存中沒有庵朝,所以調(diào)用waitForExistingOrStartNewJob()方法獲取

  private <R> LoadStatus waitForExistingOrStartNewJob(
      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,
      Executor callbackExecutor,
      EngineKey key,
      long startTime) {
    //獲取緩存的EngineJob
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      //添加回調(diào)
      current.addCallback(cb, callbackExecutor);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }
    //構(gòu)建EngineJob
    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);
    //構(gòu)建DecodeJob吗冤,其中DecodeJob是實(shí)現(xiàn)了Runnable
    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, callbackExecutor);
    //開始執(zhí)行
    engineJob.start(decodeJob);

    if (VERBOSE_IS_LOGGABLE) {
      logWithTimeAndKey("Started new load", startTime, key);
    }
    return new LoadStatus(cb, engineJob);
  }

上面中engineJob.start(decodeJob);就是通過一個(gè)線程池來(lái)執(zhí)行Runnable又厉,因?yàn)镈ecodeJob實(shí)現(xiàn)了Runnable,所以會(huì)走到DecodeJob的run方法中

  @Override
  public void run() {
      //...
     
      runWrapped();
      //.....
  }

  private void runWrapped() {
    //runReason默認(rèn)為INITIALIZE
    switch (runReason) {
      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);
    }
  }

上面這里就有點(diǎn)像策略模式椎瘟,通過不同的策略來(lái)獲取資源覆致,也就是通過本地或網(wǎng)絡(luò)獲取圖片,獲取到對(duì)應(yīng)的策略之后調(diào)用runGenerators()方法

  private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    //調(diào)用對(duì)應(yīng)的startNext()方法
    while (!isCancelled
        && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      //如果startNext()返回false肺蔚,則獲取下一個(gè)Generator煌妈,
      //也就是策略,然后在調(diào)用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.
  }

根據(jù)getNextGenerator()方法返回的Generator來(lái)看宣羊,當(dāng)?shù)谝淮握?qǐng)求是璧诵,會(huì)走到SourceGenerator的startNext()方法中,也就是從網(wǎng)絡(luò)中獲取仇冯,我們看SourceGenerator的startNext()方法

  @Override
  public boolean startNext() {
    //第一次dataToCache為null
    if (dataToCache != null) {
      Object data = dataToCache;
      dataToCache = null;
      cacheData(data);
    }
    //sourceCacheGenerator也為null
    if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
      return true;
    }
    sourceCacheGenerator = null;

    loadData = null;
    boolean started = false;
    //通過while之宿,來(lái)獲取
    while (!started && hasNextModelLoader()) {
      //獲取可用的獲取資源列表
      loadData = helper.getLoadData().get(loadDataListIndex++);
      //判斷是否可用
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
              || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        //可用將started至為true
        started = true;
        //獲取資源
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }

其中這里是我覺得比較繞的地方,就是如何判斷獲取的是哪個(gè)苛坚,先來(lái)看helper.getLoadData()獲取的列表是什么

  List<LoadData<?>> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
      //獲取前面注冊(cè)的比被,這里的model就是我們的string類型地址
      List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
      //noinspection ForLoopReplaceableByForEach to improve perf
      for (int i = 0, size = modelLoaders.size(); i < size; i++) {
        ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
        //注意這里,調(diào)用了buildLoadData()方法
        LoadData<?> current = modelLoader.buildLoadData(model, width, height, options);
        if (current != null) {
          loadData.add(current);
        }
      }
    }
    return loadData;
  }

又通過glideContext.getRegistry().getModelLoaders(model);來(lái)獲取

  @NonNull
  public <Model> List<ModelLoader<Model, ?>> getModelLoaders(@NonNull Model model) {
    //通過getModelLoaders方法獲取
    List<ModelLoader<Model, ?>> result = modelLoaderRegistry.getModelLoaders(model);
    if (result.isEmpty()) {
      throw new NoModelLoaderAvailableException(model);
    }
    return result;
  }

  @NonNull
  public <A> List<ModelLoader<A, ?>> getModelLoaders(@NonNull A model) {
    //通過getModelLoadersForClass獲取
    List<ModelLoader<A, ?>> modelLoaders = getModelLoadersForClass(getClass(model));
    int size = modelLoaders.size();
    boolean isEmpty = true;
    List<ModelLoader<A, ?>> filteredLoaders = Collections.emptyList();
    //noinspection ForLoopReplaceableByForEach to improve perf
    for (int i = 0; i < size; i++) {
      ModelLoader<A, ?> loader = modelLoaders.get(i);
      //判斷是否可用
      if (loader.handles(model)) {
        if (isEmpty) {
          filteredLoaders = new ArrayList<>(size - i);
          isEmpty = false;
        }
        //如果可用泼舱,添加到filteredLoaders中
        filteredLoaders.add(loader);
      }
    }
    return filteredLoaders;
  }

這里又通過getModelLoadersForClass()方法來(lái)獲取

  @NonNull
  private synchronized <A> List<ModelLoader<A, ?>> getModelLoadersForClass(
      @NonNull Class<A> modelClass) {
    //通過緩存獲取
    List<ModelLoader<A, ?>> loaders = cache.get(modelClass);
    if (loaders == null) {
      //緩存為null等缀,通過multiModelLoaderFactory.build(modelClass)方法獲取
      //其中modelClass為String.class
      loaders = Collections.unmodifiableList(multiModelLoaderFactory.build(modelClass));
      cache.put(modelClass, loaders);
    }
    return loaders;
  }

又通過multiModelLoaderFactory.build(modelClass)來(lái)獲取,需要注意的是modelClass為String.class

  @NonNull
  synchronized <Model> List<ModelLoader<Model, ?>> build(@NonNull Class<Model> modelClass) {
    try {
      List<ModelLoader<Model, ?>> loaders = new ArrayList<>();
      //循環(huán)entries
      for (Entry<?, ?> entry : entries) {
        //如果已經(jīng)添加了娇昙,continue
        if (alreadyUsedEntries.contains(entry)) {
          continue;
        }
        //判斷是否可用
        if (entry.handles(modelClass)) {
          alreadyUsedEntries.add(entry);
          //如果可用尺迂,調(diào)用build方法,build方法就是:entry.factory.build(this)
          loaders.add(this.<Model, Object>build(entry));
          alreadyUsedEntries.remove(entry);
        }
      }
      return loaders;
    } catch (Throwable t) {
      alreadyUsedEntries.clear();
      throw t;
    }
  }

其中entries是在Glide構(gòu)造方法中添加數(shù)據(jù)的

//構(gòu)造方法中冒掌,就是通過append來(lái)給前面的entries數(shù)組添加值的
registry
        .append(ByteBuffer.class, new ByteBufferEncoder())
//...

根據(jù)前面的噪裕,因?yàn)閙odelClass為String.class,所以只需要找下面這些

.append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>())
.append(String.class, InputStream.class, new StringLoader.StreamFactory())
.append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
.append(
            String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory())

其中第三個(gè)參數(shù)就是factory宋渔,所以這里添加的就是這里對(duì)應(yīng)的factory中build方法返回的然后現(xiàn)在往回走州疾,回到helper.getLoadData()方法中

  List<LoadData<?>> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
      //我們已經(jīng)知道了這個(gè)list里的值是什么了
      List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
      //noinspection ForLoopReplaceableByForEach to improve perf
      for (int i = 0, size = modelLoaders.size(); i < size; i++) {
        ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
        //調(diào)用buildLoadData()方法
        LoadData<?> current = modelLoader.buildLoadData(model, width, height, options);
        if (current != null) {
          loadData.add(current);
        }
      }
    }
    return loadData;
  }

然后再調(diào)用buildLoadData()方法辜限,就是前面我們看的factory.build()返回值的buildLoadData()方法皇拣,我以第一個(gè)來(lái)舉例,也就是DataUrlLoader.StreamFactory<String>()

    @NonNull
    @Override
    public ModelLoader<Model, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {
      //返回DataUrlLoader對(duì)象
      return new DataUrlLoader<>(opener);
    }

這個(gè)返回的是一個(gè)DataUrlLoader對(duì)象

  public DataUrlLoader(DataDecoder<Data> dataDecoder) {
    this.dataDecoder = dataDecoder;
  }

  @Override
  public LoadData<Data> buildLoadData(
      @NonNull Model model, int width, int height, @NonNull Options options) {
    //正常會(huì)走來(lái)這里
    return new LoadData<>(
        new ObjectKey(model), new DataUriFetcher<>(model.toString(), dataDecoder));
  }

  @Override
  public boolean handles(@NonNull Model model) {
    //注意這里返回的false
    return model.toString().startsWith(DATA_SCHEME_IMAGE);
  }

正常會(huì)走buildLoadData()方法薄嫡,但是這里handles()方法判斷返回的是false氧急,前面我們?cè)谔砑拥臅r(shí)候會(huì)判斷handles()方法,如果返回false毫深,則不添加吩坝,所以這個(gè)不符合,會(huì)走到下一個(gè)哑蔫,也就是StringLoader.StreamFactory()中

    @NonNull
    @Override
    public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {
      //返回StringLoader钉寝,注意這里里面又調(diào)用了multiFactory.build(Uri.class, InputStream.class)
      //相當(dāng)于又從新找了一遍
      return new StringLoader<>(multiFactory.build(Uri.class, InputStream.class));
    }

返回StringLoader弧呐,去看StringLoader

  public StringLoader(ModelLoader<Uri, Data> uriLoader) {
    this.uriLoader = uriLoader;
  }

  @Override
  public LoadData<Data> buildLoadData(
      @NonNull String model, int width, int height, @NonNull Options options) {
    Uri uri = parseUri(model);
    //判斷又判斷了handles
    if (uri == null || !uriLoader.handles(uri)) {
      return null;
    }
    //返回的是buildLoadData()方法
    return uriLoader.buildLoadData(uri, width, height, options);
  }

  @Override
  public boolean handles(@NonNull String model) {
    //這里返回true
    return true;
  }

所以,又調(diào)了一遍multiFactory.build(Uri.class, InputStream.class)嵌纲,注意這里的類型變成了Uri.class, InputStream.class俘枫,所以我們?cè)谌lide構(gòu)造方法中找對(duì)應(yīng)的

.append(Uri.class, InputStream.class, new DataUrlLoader.StreamFactory<Uri>())
.append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
.append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))
.append(Uri.class, InputStream.class, new MediaStoreImageThumbLoader.Factory(context))
        .append(Uri.class, InputStream.class, new MediaStoreVideoThumbLoader.Factory(context))
        .append(Uri.class, InputStream.class, new UriLoader.StreamFactory(contentResolver))
.append(Uri.class, InputStream.class, new UrlUriLoader.StreamFactory())

然后又通過factory.build()的返回值的來(lái)判斷handle()方法,到這里逮走,然后回到最開始的地方

//還記得這個(gè)循環(huán)嗎鸠蚪,前面獲取的
while (!started && hasNextModelLoader()) {
      //現(xiàn)在我們已經(jīng)知道這個(gè)list里的內(nèi)容是什么了
      loadData = helper.getLoadData().get(loadDataListIndex++);
      //通過這里來(lái)判斷l(xiāng)oadData.fetcher.getDataSourc
      //其中l(wèi)oadData.fetcher就是我們factory.build()的返回值的buildLoadData()方法返回的內(nèi)容
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
              || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }

根據(jù)helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource()這個(gè)判斷,我們找到可用的就是下面這個(gè)

.append(Uri.class, InputStream.class, new HttpUriLoader.Factory())

來(lái)看這個(gè)factory

    public ModelLoader<Uri, InputStream> build(MultiModelLoaderFactory multiFactory) {
      //又來(lái)一遍师溅,不過類型變成了GlideUrl.class, InputStream.class
      return new HttpUriLoader(multiFactory.build(GlideUrl.class, InputStream.class));
    }

  public HttpUriLoader(ModelLoader<GlideUrl, InputStream> urlLoader) {
    this.urlLoader = urlLoader;
  }

  @Override
  public LoadData<InputStream> buildLoadData(
      @NonNull Uri model, int width, int height, @NonNull Options options) {
    return urlLoader.buildLoadData(new GlideUrl(model.toString()), width, height, options);
  }

  @Override
  public boolean handles(@NonNull Uri model) {
    return SCHEMES.contains(model.getScheme());
  }

又來(lái)一遍茅信,但是類型變成了GlideUrl.class, InputStream.class,這個(gè)類型只有一個(gè)

.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())

繼續(xù)看這個(gè)factory

    @NonNull
    @Override
    public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
      return new HttpGlideUrlLoader(modelCache);
    }

  public HttpGlideUrlLoader(@Nullable ModelCache<GlideUrl, GlideUrl> modelCache) {
    this.modelCache = modelCache;
  }

  @Override
  public LoadData<InputStream> buildLoadData(
      @NonNull GlideUrl model, int width, int height, @NonNull Options options) {
    // GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time
    // spent parsing urls.
    GlideUrl url = model;
    if (modelCache != null) {
      url = modelCache.get(model, 0, 0);
      if (url == null) {
        modelCache.put(model, 0, 0, model);
        url = model;
      }
    }
    int timeout = options.get(TIMEOUT);
    //最后會(huì)返回的是這里
    return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
  }

  @Override
  public boolean handles(@NonNull GlideUrl model) {
    return true;
  }

所以loadData.fetcher.loadData(helper.getPriority(), this);中的fetcher就是上面的HttpUrlFetcher墓臭。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蘸鲸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子窿锉,更是在濱河造成了極大的恐慌棚贾,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榆综,死亡現(xiàn)場(chǎng)離奇詭異妙痹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鼻疮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門怯伊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人判沟,你說我怎么就攤上這事耿芹。” “怎么了挪哄?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵吧秕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我迹炼,道長(zhǎng)砸彬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任斯入,我火速辦了婚禮砂碉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刻两。我一直安慰自己增蹭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布磅摹。 她就那樣靜靜地躺著滋迈,像睡著了一般霎奢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上饼灿,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天椰憋,我揣著相機(jī)與錄音,去河邊找鬼赔退。 笑死橙依,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的硕旗。 我是一名探鬼主播窗骑,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼漆枚!你這毒婦竟也來(lái)了创译?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤墙基,失蹤者是張志新(化名)和其女友劉穎软族,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體残制,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡立砸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了初茶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颗祝。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖恼布,靈堂內(nèi)的尸體忽然破棺而出螺戳,到底是詐尸還是另有隱情,我是刑警寧澤折汞,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布倔幼,位于F島的核電站,受9級(jí)特大地震影響爽待,放射性物質(zhì)發(fā)生泄漏损同。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一堕伪、第九天 我趴在偏房一處隱蔽的房頂上張望揖庄。 院中可真熱鬧,春花似錦欠雌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)禁炒。三九已至,卻和暖如春霍比,著一層夾襖步出監(jiān)牢的瞬間幕袱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工悠瞬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留们豌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓浅妆,卻偏偏與公主長(zhǎng)得像望迎,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凌外,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容