Android Glide 基于4.8.0的源码分析

# 前言

开始学习Android接触过比较老的框架ImageLoade,刚开始看着东西只是一头雾水,只知道使用,一旦涉及到框架问题几乎解决不了,就怪框架,所以多了解下框架的实现原理对以后的处理问题有着很好的作用,如有错误请多指正,谢谢!最后希望大家一起保持学习精神。

## Glide 构造方法

首先我们来看Glide的构造方法

```

Glide(

      @NonNull Context context,

      @NonNull Engine engine,

      @NonNull MemoryCache memoryCache,

      @NonNull BitmapPool bitmapPool,

      @NonNull ArrayPool arrayPool,

      @NonNull RequestManagerRetriever requestManagerRetriever,

      @NonNull ConnectivityMonitorFactory connectivityMonitorFactory,

      int logLevel,

      @NonNull RequestOptions defaultRequestOptions,

      @NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions) {

    this.engine = engine;

    this.bitmapPool = bitmapPool;

    this.arrayPool = arrayPool;

    this.memoryCache = memoryCache;

    this.requestManagerRetriever = requestManagerRetriever;

    this.connectivityMonitorFactory = connectivityMonitorFactory;

    DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);

    bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);

    final Resources resources = context.getResources();

    registry = new Registry();

    registry

    .append(ByteBuffer.class, new ByteBufferEncoder())


    }

```

接下来看下默认编码格式。

```

  DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);

  DECODE_FORMAT = Option.memory("com.bumptech.glide.load.resource.bitmap.Downsampler.DecodeFormat" DecodeFormat.DEFAULT);

  DEFAULT = PREFER_ARGB_8888;

```

看到源码默认的图片解码格式为ARGB_8888,和Picasso的默认格式相同了(貌似以前是RGB565)这个会多占内存了但是速度却快了,这需要牺牲空间换来换取更多的时间。

## 通过分解执行步骤来解读源码

### 一、Glide.With(context)


    Glide.with(context).load("url").into(ImageView)

我们平时就是这样调用的,有些配置在这里我省略了,读源码应该先从整体提流程下手,要不然会陷入代码的深渊里。


#### (1)  getRetriever(context) 返回

Glide.With(context)是个静态方法直接可以调用我们来看下边实现。

  ```

    @NonNull

  public static RequestManager with(@NonNull Context context) {

    return getRetriever(context).get(context);

  }

  ```

这里返回个 RequestManager 类型,我们来看下  getRetriever(context) 返回RequestManagerRetriever 类型。


  ```

  @NonNull

  private static RequestManagerRetriever getRetriever(@Nullable Context context) {

    // Context could be null for other reasons (ie the user passes in null), but in practice it will

    // only occur due to errors with the Fragment lifecycle.

    Preconditions.checkNotNull(

        context,

        "You cannot start a load on a not yet attached View or a Fragment where getActivity() "

            + "returns null (which usually occurs when getActivity() is called before the Fragment "

            + "is attached or after the Fragment is destroyed).");

    return Glide.get(context).getRequestManagerRetriever();

  }

  ```

  再看一下Glide.get(context)这里实际上是通过单例模式初始化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());

  }

  ```

  ```

  private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {

    Context applicationContext = context.getApplicationContext();

    GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();

    //这里的操作是通过Manifest的meta_data获取配置进行注册

    List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();

    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {

      manifestModules = new ManifestParser(applicationContext).parse();

    }

    if (annotationGeneratedModule != null

        && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {

      Set<Class<?>> excludedModuleClasses =

          annotationGeneratedModule.getExcludedModuleClasses();

      Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();

      while (iterator.hasNext()) {

        com.bumptech.glide.module.GlideModule current = iterator.next();

        if (!excludedModuleClasses.contains(current.getClass())) {

          continue;

        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {

          Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);

        }

        iterator.remove();

      }

    }

    if (Log.isLoggable(TAG, Log.DEBUG)) {

      for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {

        Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());

      }

    }

      //创建 RequestManagerFactory 获取工厂模式的对象后边会根据它作为参数初始化RequestManagerRetriever


    RequestManagerRetriever.RequestManagerFactory factory =

        annotationGeneratedModule != null

            ? annotationGeneratedModule.getRequestManagerFactory() : null;

    builder.setRequestManagerFactory(factory);

    for (com.bumptech.glide.module.GlideModule module : manifestModules) {

      module.applyOptions(applicationContext, builder);

    }

    if (annotationGeneratedModule != null) {

      annotationGeneratedModule.applyOptions(applicationContext, builder);

    }

    //通过构建者模式穿建Glide对象并且记载配置初始参数

    Glide glide = builder.build(applicationContext);

    for (com.bumptech.glide.module.GlideModule module : manifestModules) {

      module.registerComponents(applicationContext, glide, glide.registry);

    }

    if (annotationGeneratedModule != null) {

      annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);

    }

    applicationContext.registerComponentCallbacks(glide);

    Glide.glide = glide;

  }

  ```


      Glide glide = builder.build(applicationContext);

builder.build内部通过构建者模式出创建实例,且初始化了 getRequestManagerRetriever 对象并且Glide内部实现了对象的getRequestManagerRetriever 方法,此时也就回到了我们最初调用的方法。getRetriever(context) 最终返回 getRequestManagerRetriever对象


  #### (2) getRetriever(context).get(context);  返回RequestManager类型对象

  我们已经得到了 getRequestManagerRetriever ,那么我们可以看下getRequestManagerRetriever内部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);

  }

  ```

看到代码我们都知道这个方法通不过不同类型的context,判断是activity还是fragment类型都调用同一重载方法get(@NonNull)通过多层判断最终执行。fragmentGet(  activity, fm,  null,isActivityVisible(activity));。

这里会创建一个FragmentManager 也就是上边的fm,方法内部会调用SupportRequestManagerFragment 方法,这个方法内部主要用于创建一个Fragment主要用来实现的Glide对Activity生命周期的感知作用(真是看了源码觉得fragment 还可以这样用)最终返回RequestManager。

```

@Deprecated

  @NonNull

  private RequestManager fragmentGet(@NonNull Context context,

      @NonNull android.app.FragmentManager fm,

      @Nullable android.app.Fragment parentHint,

      boolean isParentVisible) {

    RequestManagerFragment current = getRequestManagerFragment(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;

  }

```

至此我们已经完成了Glide.With(context)分析。

### 二、Glide.with(context).load("url")

#### (1) 首先我们看RequestManager.load也就是我们调用的Load方法

```

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

  }

```

asDrawable()调用创建了RequestBuilder对象并且返回。

#### (2) 此时我们看RequestBuilder.load函数

```

@NonNull

  @Override

  @CheckResult

  public RequestBuilder<TranscodeType> load(@Nullable String string) {

    return loadGeneric(string);

  }

@NonNull

  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {

    this.model = model;

    isModelSet = true;

    return this;

  }

```

至此 Glide.with(context).load("url"),已经调用完成。我指写了大概的调用过程,细节地方请自行翻看源码体会。

### 三、Glide.with(context).load("url").into()。

#### (1) into()方法

```

@NonNull

  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {

    Util.assertMainThread();

    Preconditions.checkNotNull(view);

    ...

    //为了减少代码长度,中间省去一些配置的代码

    ...

    //此处比较重要

    return into(

        glideContext.buildImageViewTarget(view, transcodeClass),

        /*targetListener=*/ null,

        requestOptions);

  }

```

在看返回的into()方法之前先看下    glideContext.buildImageViewTarget(view, transcodeClass)方法 代码不粘贴说下内部实现,buildImageViewTarget 根据传入的参数不同生成不同的ViewTarget,后边target就是指ViewTarget,实现类分别为BitmapImageViewTarget、DrawableImageViewTarget,代码省略请自行查看,接下来我们看return的into()方法。

```

  private <Y extends Target<TranscodeType>> Y into(

      @NonNull Y target,

      @Nullable RequestListener<TranscodeType> targetListener,

      @NonNull RequestOptions options) {

    Util.assertMainThread();

    Preconditions.checkNotNull(target);

    if (!isModelSet) {

      throw new IllegalArgumentException("You must call #load() before calling #into()");

    }

    options = options.autoClone();

    //通过我们传过来的target来创建新的request对象

    Request request = buildRequest(target, targetListener, options);

    //通过target来获取上一个request对象,target会存储上一个request

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

    //开始执行track 下载

    requestManager.track(target, request);

    return target;

  }

```

Request 对像通过buildRequest来创建的,查看源码可知最终实现是SingleRequest类,然后道接下来要执行requestManager.track(target, request),下面贴代码。

```

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

    targetTracker.track(target);

    requestTracker.runRequest(request);

  }

```

看下requestTracker.runRequest(request);

```

  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() ,我们看下renquest的实现类,SingleRequest类的begin()方法。

```

    @Override

  public void begin() {

    ...

    status = Status.WAITING_FOR_SIZE;

    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {

      onSizeReady(overrideWidth, overrideHeight);

    } else {

      target.getSize(this);

    }

  ...

  }

```

省去部分代码当status不为COMPLETE时且已确定图片尺寸大小,则执行 onSizeReady(overrideWidth, overrideHeight)代码。

```

  @Override

  public void onSizeReady(int width, int height) {

...

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

  ...

  }

```

继续执行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) {

    Util.assertMainThread();

    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;

  //获取当前请求的key

    EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,

        resourceClass, transcodeClass, options);

  // 这里会从activity资源获取是否有缓存,如果有缓存就直接返回回调。

    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);

    if (active != null) {

      cb.onResourceReady(active, DataSource.MEMORY_CACHE);

      if (VERBOSE_IS_LOGGABLE) {

        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 (VERBOSE_IS_LOGGABLE) {

        logWithTimeAndKey("Loaded resource from cache", startTime, key);

      }

      return null;

    }

    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);

    if (current != null) {

      current.addCallback(cb);

      if (VERBOSE_IS_LOGGABLE) {

        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 (VERBOSE_IS_LOGGABLE) {

      logWithTimeAndKey("Started new load", startTime, key);

    }

    return new LoadStatus(cb, engineJob);

  }

```

load()方法会创建,EngineJob、DecodeJob,并且执行engineJob.start(decodeJob)再看下此方法,

```

public void start(DecodeJob<R> decodeJob) {

    this.decodeJob = decodeJob;

    GlideExecutor executor = decodeJob.willDecodeFromCache()

        ? diskCacheExecutor

        : getActiveSourceExecutor();

    executor.execute(decodeJob);

  }

```

DecodeJob实现了Runnable接口,上述代码可以看到将DecodeJob的放到了线程池中进行执行,这时候已经将代码切换到另一个线程处理了,接下来应该查看将DecodeJob的run方法。

```

  @Override

  public void run() {

    GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);

    DataFetcher<?> localFetcher = currentFetcher;

    try {

      if (isCancelled) {

        notifyFailed();

        return;

      }

      runWrapped();

    } catch (Throwable t) {

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

      }

      GlideTrace.endSection();

    }

  }

```

里边主要执行 runWrapped(),方法接着贴出来。

```

private void runWrapped() {

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

    }

  }

```

stage = getNextStage(Stage.INITIALIZE);会进一步判断是否为为磁盘缓存,然后返回相应的状态,然后会执行runGenerators()方法,首先会获取currentGenerator对象,它会根据stage返回相应的DataFetcherGenerator对象后边会用到。

```

  private void runGenerators() {

    currentThread = Thread.currentThread();

    startFetchTime = LogTime.getLogTime();

    boolean isStarted = false;

    while (!isCancelled && currentGenerator != null

    //这里会执行currentGenerator.startNext()

        && !(isStarted = currentGenerator.startNext())) {

      stage = getNextStage(stage);

      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {

        reschedule();

        return;

      }

    }

    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {

      notifyFailed();

    }

  }

```

来看currentGenerator.startNext() 他的实现类这时应该是

```

@Override

  public boolean startNext() {

  //dataToCache如果不为空那么会进行像磁盘缓存

    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;

  }

```

loadData的实现类为MultiModelLoader,loadData.fetcher的实现为MultiFetcher。接下来我们看下MultiFetcher的loadData()MultiFetcher是MultiModelLoader的内部类。

```

  @Override

    public void loadData(

        @NonNull Priority priority, @NonNull DataCallback<? super Data> callback) {

      this.priority = priority;

      this.callback = callback;

      exceptions = throwableListPool.acquire

      //真正调用网络加载

      fetchers.get(currentIndex).loadData(priority, this);

    }

```

这里在外部是可以自定义下载类,因为没有自定义,所以会默认执行HttpUriLoader的loadData()方法

```

  @Override

  public void loadData(@NonNull Priority priority,

      @NonNull DataCallback<? super InputStream> callback) {

    long startTime = LogTime.getLogTime();

    try {

    //调用系统方法返回输入流

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

      }

      callback.onLoadFailed(e);

    } finally {

      if (Log.isLoggable(TAG, Log.VERBOSE)) {

        Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));

      }

    }

  }

  //调用urlConnection

    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 {

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

    }

  }

```

成功下载后回回调  callback.onDataReady(result)方法,这个callback是MultiFetcher对象,看他的实现方法

```

  @Override

    public void onDataReady(@Nullable Data data) {

      if (data != null) {

        callback.onDataReady(data);

      } else {

        startNextOrFail();

      }

    }

```

继续回调 callback.onDataReady(data);这个callback是SourceGenerator对象,那么继续看它的回调方法。

```

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

    }

  }

```

这是会调用 cb.reschedule();这个cb回调是DecodeJob对象实现的继续看回调方法,

```

@Override

  public void reschedule() {

    runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;

    callback.reschedule(this);

  }

```

这时将runReason更改为RunReason.SWITCH_TO_SOURCE_SERVICE状态。callback 是EngineJob对象,我们看EngineJob.reschedule(this)方法。

```

  @Override

  public void reschedule(DecodeJob<?> job) {

    // Even if the job is cancelled here, it still needs to be scheduled so that it can clean itself

    // up.

    getActiveSourceExecutor().execute(job);

  }

```

上述方法又会放到线程池中执行DecodeJob的run方法。但是这时runReason已经切换为SWITCH_TO_SOURCE_SERVICE状态继续看run()方法的runWrapped()。

```

  private void runWrapped() {

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

    }

  }

```

这时直接运行runGenerators()

```

  private void runGenerators() {

    currentThread = Thread.currentThread();

    startFetchTime = LogTime.getLogTime();

    boolean isStarted = false;

    while (!isCancelled && currentGenerator != null

        && !(isStarted = currentGenerator.startNext())) {

      stage = getNextStage(stage);

      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {

        reschedule();

        return;

      }

    }

    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {

      notifyFailed();

    }

  }

```

这时仍会执行currentGenerator.startNext()

```

@Override

  public boolean startNext() {

    ...

    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;

  }

```

loadData的这次实现是ByteBufferFileLoade,loadData.fetcher的实现是ByteBufferFetcher,因为获取时getLoadData的索引递增的。所以看下ByteBufferFetcher的loadData()方法。

```

  @Override

    public void loadData(@NonNull Priority priority,

        @NonNull DataCallback<? super ByteBuffer> callback) {

      ByteBuffer result;

      try {

        result = ByteBufferUtil.fromFile(file);

      } catch (IOException e) {

        if (Log.isLoggable(TAG, Log.DEBUG)) {

          Log.d(TAG, "Failed to obtain ByteBuffer for file", e);

        }

        callback.onLoadFailed(e);

        return;

      }

      callback.onDataReady(result);

    }

```

由源码可知道,数据result从文件中加载,这个callback是DataCacheGenerator,看下他的回调实现。

```

@Override

  public void onDataReady(Object data) {

    cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);

  }

```

cb是SourceGenerator,看它的回调。

```

  @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.onDataFetcherReady(sourceKey, data, fetcher, loadData.fetcher.getDataSource(), sourceKey);

  }

```

这个cb是DecodeJob对象,继续看回调。

```

@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 {

      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");

      try {

        decodeFromRetrievedData();

      } finally {

        GlideTrace.endSection();

      }

    }

  }

  ```

这是因为他们不再同一个线程所以执行 decodeFromRetrievedData()方法。

```

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

    }

  }

```

执行    notifyEncodeAndRelease(resource, currentDataSource);

```

private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {

  ...

    notifyComplete(result, dataSource);

  ...

  }

private void notifyComplete(Resource<R> resource, DataSource dataSource) {

    setNotifiedOrThrow();

    callback.onResourceReady(resource, dataSource);

  }

```

这时又会回调给EngineJob来进行处理

```

  @Override

  public void onResourceReady(Resource<R> resource, DataSource dataSource) {

    this.resource = resource;

    this.dataSource = dataSource;

    MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();

  }

```

执行到此时我们看到了obtainMessage进行线程换到主线程来进行图片处理,handlermessage处理如下,

```

    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() {

...

    for (int i = 0, size = cbs.size(); i < size; i++) {

      ResourceCallback cb = cbs.get(i);

      if (!isInIgnoredCallbacks(cb)) {

        engineResource.acquire();

        cb.onResourceReady(engineResource, dataSource);

      }

    }

...

  }

```

cb是SingleRequest继续看回调方法SingleRequest.onResourceReady。

```

  @SuppressWarnings("unchecked")

  @Override

  public void onResourceReady(Resource<?> resource, DataSource dataSource) {

    ...

    onResourceReady((Resource<R>) resource, (R) received, dataSource);

  }

```

接着往下走(说实话走到这我都奔溃了代码太复杂了)

```

  private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {

    ...

    try {

    ...

      if (!anyListenerHandledUpdatingTarget) {

        Transition<? super R> animation =

            animationFactory.build(dataSource, isFirstResource);

        //这里即将调用设置图片的方法

        target.onResourceReady(result, animation);

      }

    } finally {

      isCallingCallbacks = false;

    }

...

  }

```

记得说过target的实现是DrawableImageViewTarget,这边要调用方法 target.onResourceReady(result, animation);这里没有看下他的父类方法。

```

  @Override

  public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {

    if (transition == null || !transition.transition(resource, this)) {

    //继续深入这个方法

      setResourceInternal(resource);

    } else {

      maybeUpdateAnimatable(resource);

    }

  }

private void setResourceInternal(@Nullable Z resource) {

  //继续深入

    setResource(resource);

    maybeUpdateAnimatable(resource);

  }

```

setResource(@Nullable Z resource),是一个抽象方法,此时回调用子类的setResource方法

```

  @Override

  protected void setResource(@Nullable Drawable resource) {

    view.setImageDrawable(resource);

  }

```

这个view是我们一开始传过来的ImageView,到最后我们已经从代码开始一直跟踪到了图片被设置到界面上的一个大致流程,有时间会写篇关于缓存的策略的分析,再见!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容