Glide源码流程分析

1.Glide.with()
  public static RequestManager with(FragmentActivity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(activity);
    }

    public RequestManager get(FragmentActivity activity) {
        if (Util.isOnBackgroundThread()) {
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            FragmentManager fm = activity.getSupportFragmentManager();
            return supportFragmentGet(activity, fm);
        }
    }

    RequestManager supportFragmentGet(Context context, FragmentManager fm) {
        SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }



      getSupportRequestManagerFragment这个方法干了啥?就是去创建一个Fragment,把这个创建的Fragment绑定到Activity,就是为了监听activity的生命周期,比如RecyclyerView一个列表
      在加载图片,这个时候退出当前Activity应该停止访问网络加载图片,绑定生命周期就有这个好处。

    SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) {
        SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
            current = pendingSupportRequestManagerFragments.get(fm);
            if (current == null) {
                // 创建一个 Fragment 绑定到 Activity 上面
                current = new SupportRequestManagerFragment();
                pendingSupportRequestManagerFragments.put(fm, current);
                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
            }
        }
        return current;
    }
     //生命周期
         RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
                    RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
                this.context = context.getApplicationContext();
                this.lifecycle = lifecycle;
                this.treeNode = treeNode;
                this.requestTracker = requestTracker;
                this.glide = Glide.get(context);
                this.optionsApplier = new OptionsApplier();

                ConnectivityMonitor connectivityMonitor = factory.build(context,
                        new RequestManagerConnectivityListener(requestTracker));

                // If we're the application level request manager, we may be created on a background thread. In that case we
                // cannot risk synchronously pausing or resuming requests, so we hack around the issue by delaying adding
                // ourselves as a lifecycle listener by posting to the main thread. This should be entirely safe.
                if (Util.isOnBackgroundThread()) {
                    new Handler(Looper.getMainLooper()).post(new Runnable() {
                        @Override
                        public void run() {
                            lifecycle.addListener(RequestManager.this);
                        }
                    });
                } else {
                    lifecycle.addListener(this);
                }
                lifecycle.addListener(connectivityMonitor);
            }
            LifecycleListener 是个接口有三个方法,onStart() , onStop(),onDestroy() 对应 RequestManager 中的实现分别是:
             /**
                         * Lifecycle callback that registers for connectivity events (if the android.permission.ACCESS_NETWORK_STATE
                         * permission is present) and restarts failed or paused requests.
                         */
                        @Override
                        public void onStart() {
                            // onStart might not be called because this object may be created after the fragment/activity's onStart method.
                            resumeRequests();
                        }

                        /**
                         * Lifecycle callback that unregisters for connectivity events (if the android.permission.ACCESS_NETWORK_STATE
                         * permission is present) and pauses in progress loads.
                         */
                        @Override
                        public void onStop() {
                            pauseRequests();
                        }

                        /**
                         * Lifecycle callback that cancels all in progress requests and clears and recycles resources for all completed
                         * requests.
                         */
                        @Override
                        public void onDestroy() {
                            requestTracker.clearRequests();
                        }
   所以总结一下Glide.with() 这方法返回的是一个 RequestManager 主要用来监听一些生命周期,以此来管理加载请求 Request 。拿 FragmentActivity 来说当 Activity 退出了会调用 onDestroy() -> requestTracker.clearRequests(); 会清理所有的图片加载请求,并且一个 FragmentActivity 只有一个 SupportRequestManagerFragment 和一个 RequestManager 。
    2.Glide.with().load()
    public DrawableTypeRequest<String> load(String string) {
            return (DrawableTypeRequest<String>) fromString().load(string);
        }

        public DrawableTypeRequest<String> fromString() {
            return loadGeneric(String.class);
        }

        private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
            ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);
            ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =
                    Glide.buildFileDescriptorModelLoader(modelClass, context);
            if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
                throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for"
                        + " which there is a registered ModelLoader, if you are using a custom model, you must first call"
                        + " Glide#register with a ModelLoaderFactory for your custom model class");
            }

            return optionsApplier.apply(
                    new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
                            glide, requestTracker, lifecycle, optionsApplier));
        }
   Glide.buildStreamModelLoader 和 Glide.buildFileDescriptorModelLoader 这两个方法看不太懂先放一边,待会再回来找他,先记住他的变量名 streamModelLoader 和 fileDescriptorModelLoader,接下来创建了一个 DrawableTypeRequest 返回。
   3.Glide.with().load().into()
   public Target<TranscodeType> into(ImageView view) {
           Util.assertMainThread();
           if (view == null) {
               throw new IllegalArgumentException("You must pass in a non null View");
           }

           return into(glide.buildImageViewTarget(view, transcodeClass));
       }

 buildTarget返回的是GlideDrawableImageViewTarget,transcodeClass是GlideDrawabe.class,在第2步load的时候赋值。
       public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {
           if (GlideDrawable.class.isAssignableFrom(clazz)) {
               return (Target<Z>) new GlideDrawableImageViewTarget(view);
           } else if (Bitmap.class.equals(clazz)) {
               return (Target<Z>) new BitmapImageViewTarget(view);
           } else if (Drawable.class.isAssignableFrom(clazz)) {
               return (Target<Z>) new DrawableImageViewTarget(view);
           } else {
               throw new IllegalArgumentException("Unhandled class: " + clazz
                       + ", try .as*(Class).transcode(ResourceTranscoder)");
           }
       }
 通过Target构建了一个Request,最后调用 requestTracker.runRequest(request);
 public <Y extends Target<TranscodeType>> Y into(Y target) {
           Util.assertMainThread();
           // 通过 target 构建一个 Request
           Request request = buildRequest(target);
           target.setRequest(request);
           lifecycle.addListener(target);
           // 看样子要执行
           requestTracker.runRequest(request);
           return target;
       }

    接下来肯定要分析一下怎么构建 buildRequest的:
   private Request buildRequest(Target<TranscodeType> target) {
               if (priority == null) {
                   priority = Priority.NORMAL;
               }
               return buildRequestRecursive(target, null);
           }

           // 这里省略了一个处理缩略图的方法,感兴趣可以自己研究一下

           // obtainRequest
           private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority,
                   RequestCoordinator requestCoordinator) {
               // 构建了一个 GenericRequest 参数很多,但我肯定都知道是啥意思
               return GenericRequest.obtain(
                       loadProvider,
                       model,
                       signature,
                       context,
                       priority,
                       target,
                       sizeMultiplier,
                       placeholderDrawable,
                       placeholderId,
                       errorPlaceholder,
                       errorId,
                       fallbackDrawable,
                       fallbackResource,
                       requestListener,
                       requestCoordinator,
                       glide.getEngine(),
                       transformation,
                       transcodeClass,
                       isCacheable,
                       animationFactory,
                       overrideWidth,
                       overrideHeight,
                       diskCacheStrategy);
           }


     buildRequest 构建的是一个 GenericRequest 实例,传递的参数很多但是我们肯定都认识,比如 placeholderId,errorId,transformation,diskCacheStrategy 等等,接下来看下真正的 runRequest() 方法:

                   requests.add(request);
                   if (!isPaused) {
                       request.begin();
                   } else {
                       pendingRequests.add(request);
                   }
               }



              @Override
               public void begin() {
                   startTime = LogTime.getLogTime();
                   if (model == null) {
                        // 异常报错显示错误图片
                       onException(null);
                       return;
                   }Draw

                   status = Status.WAITING_FOR_SIZE;
                   if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
                       onSizeReady(overrideWidth, overrideHeight);
                   } else {
                       target.getSize(this);
                   }

                   if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
                       target.onLoadStarted(getPlaceholderDrawable());
                   }
                   if (Log.isLoggable(TAG, Log.VERBOSE)) {
                       logV("finished run method in " + LogTime.getElapsedMillis(startTime));
                   }
               }
             然后,调用onSizeReady方法,真正的资源加载就是从这个方法中开始的。
               @Override
               public void onSizeReady(int width, int height) {
                   if (Log.isLoggable(TAG, Log.VERBOSE)) {
                       logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
                   }
                   if (status != Status.WAITING_FOR_SIZE) {
                       return;
                   }
                   status = Status.RUNNING;

                   width = Math.round(sizeMultiplier * width);
                   height = Math.round(sizeMultiplier * height);

                   ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
                   final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);

                   if (dataFetcher == null) {
                       // 异常报错显示错误图片
                       onException(new Exception("Failed to load model: \'" + model + "\'"));
                       return;
                   }
                   ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
                   if (Log.isLoggable(TAG, Log.VERBOSE)) {
                       logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
                   }
                   loadedFromMemoryCache = true;
                   loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
                           priority, isMemoryCacheable, diskCacheStrategy, this);
                   loadedFromMemoryCache = resource != null;
                   if (Log.isLoggable(TAG, Log.VERBOSE)) {
                       logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
                   }
               }
 接下来看下 engine.load() 方法:

     public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
             DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
             Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
         Util.assertMainThread();
         long startTime = LogTime.getLogTime();

         final String id = fetcher.getId();
         EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
                 loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
                 transcoder, loadProvider.getSourceEncoder());
  //处理缓存
         EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
         if (cached != null) {
             cb.onResourceReady(cached);
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 logWithTimeAndKey("Loaded resource from cache", startTime, key);
             }
             return null;
         }

         EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
         if (active != null) {
             cb.onResourceReady(active);
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 logWithTimeAndKey("Loaded resource from active resources", startTime, key);
             }
             return null;
         }

         EngineJob current = jobs.get(key);
         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 engineJob = engineJobFactory.build(key, isMemoryCacheable);
         //one
         DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
                 transcoder, diskCacheProvider, diskCacheStrategy, priority);
         //two
         EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
         jobs.put(key, engineJob);
         engineJob.addCallback(cb);
         //three 开启线程
         engineJob.start(runnable);

         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             logWithTimeAndKey("Started new load", startTime, key);
         }
         return new LoadStatus(cb, engineJob);
     }
  我们看看EngineRunnable的run 方法:

      EngineRunnable.run()
      @Override
          public void run() {
              if (isCancelled) {
                  return;
              }

              Exception exception = null;
              Resource<?> resource = null;
              try {
                  resource = decode();
              } catch (Exception e) {
                  if (Log.isLoggable(TAG, Log.VERBOSE)) {
                      Log.v(TAG, "Exception decoding", e);
                  }
                  exception = e;
              }

              if (isCancelled) {
                  // 如果被取消了,回收资源,不在往下执行
                  if (resource != null) {
                      resource.recycle();
                  }
                  return;
              }

              if (resource == null) {
                  // 失败
                  onLoadFailed(exception);
              } else {
                  // 处理成功
                  onLoadComplete(resource);
              }
          }
  先来看看EngineRunnable. decode方法:
  private Resource<?> decode() throws Exception {
          // 判断缓存
          if (isDecodingFromCache()) {
              return decodeFromCache();
          } else {
              return decodeFromSource();
          }
      }
最终调用的是 decodeJob.decodeFromSource() 方法,decodeFromSource()方法,其实它的工作分为两部,第一步是调用decodeSource()方法来获得一个Resource对象,第二步是调用transformEncodeAndTranscode()方法来处理这个Resource对象。


      public Resource<Z> decodeFromSource() throws Exception {
              Resource<T> decoded = decodeSource();
              return transformEncodeAndTranscode(decoded);
          }

          private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {
              long startTime = LogTime.getLogTime();
              Resource<T> transformed = transform(decoded);
              if (Log.isLoggable(TAG, Log.VERBOSE)) {
                  logWithTimeAndKey("Transformed resource from source", startTime);
              }

              writeTransformedToCache(transformed);

              startTime = LogTime.getLogTime();
              Resource<Z> result = transcode(transformed);
              if (Log.isLoggable(TAG, Log.VERBOSE)) {
                  logWithTimeAndKey("Transcoded transformed from source", startTime);
              }
              return result;
          }

     在 decodeSource() 方法中调用了 fetcher.loadData(priority) 和decodeFromSourceData(data);

          private Resource<T> decodeSource() throws Exception {
              Resource<T> decoded = null;
              try {
                  long startTime = LogTime.getLogTime();
                  final A data = fetcher.loadData(priority);
                  if (Log.isLoggable(TAG, Log.VERBOSE)) {
                      logWithTimeAndKey("Fetched data", startTime);
                  }
                  if (isCancelled) {
                      return null;
                  }
                  decoded = decodeFromSourceData(data);
              } finally {
                  fetcher.cleanup();
              }
              return decoded;
          }

  loadData() 方法如下,主要获取网络输入流。
        @Override
        public ImageVideoWrapper loadData(Priority priority) throws Exception {
            InputStream is = null;
            if (streamFetcher != null) {
                try {
                    is = streamFetcher.loadData(priority);
                } catch (Exception e) {
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "Exception fetching input stream, trying ParcelFileDescriptor", e);
                    }
                    if (fileDescriptorFetcher == null) {
                        throw e;
                    }
                }
            }
            ParcelFileDescriptor fileDescriptor = null;
            if (fileDescriptorFetcher != null) {
                try {
                    fileDescriptor = fileDescriptorFetcher.loadData(priority);
                } catch (Exception e) {
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "Exception fetching ParcelFileDescriptor", e);
                    }
                    if (is == null) {
                        throw e;
                    }
                }
            }
            return new ImageVideoWrapper(is, fileDescriptor);
        }
        接着回到上面去看下 decodeFromSourceData 这个方法:
            private Resource<T> decodeFromSourceData(A data) throws IOException {
                final Resource<T> decoded;
                if (diskCacheStrategy.cacheSource()) {
                    decoded = cacheAndDecodeSourceData(data);
                } else {
                    long startTime = LogTime.getLogTime();
                    //one
                    decoded = loadProvider.getSourceDecoder().decode(data, width, height);
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        logWithTimeAndKey("Decoded from source", startTime);
                    }
                }
                return decoded;
            }

   loadProvider 就是刚才在 onSizeReady() 方法中得到的FixedLoadProvider,而 getSourceDecoder() 得到的则是一个 GifBitmapWrapperResourceDecoder 对象,也就是要调用这个对象的 decode() 方法来对图片进行解码。
   那么我们来看下 GifBitmapWrapperResourceDecoder 的代码:

    @Override
    public Resource<GifBitmapWrapper> decode(ImageVideoWrapper source, int width, int height) throws IOException {
        ByteArrayPool pool = ByteArrayPool.get();
        byte[] tempBytes = pool.getBytes();

        GifBitmapWrapper wrapper = null;
        try {
            wrapper = decode(source, width, height, tempBytes);
        } finally {
            pool.releaseBytes(tempBytes);
        }
        return wrapper != null ? new GifBitmapWrapperResource(wrapper) : null;
    }

    private GifBitmapWrapper decode(ImageVideoWrapper source, int width, int height, byte[] bytes) throws IOException {
        final GifBitmapWrapper result;
        if (source.getStream() != null) {
            result = decodeStream(source, width, height, bytes);
        } else {
            result = decodeBitmapWrapper(source, width, height);
        }
        return result;
    }

    private GifBitmapWrapper decodeStream(ImageVideoWrapper source, int width, int height, byte[] bytes)
            throws IOException {
        InputStream bis = streamFactory.build(source.getStream(), bytes);
        bis.mark(MARK_LIMIT_BYTES);
        ImageHeaderParser.ImageType type = parser.parse(bis);
        bis.reset();

        GifBitmapWrapper result = null;
        //one
        if (type == ImageHeaderParser.ImageType.GIF) {
            result = decodeGifWrapper(bis, width, height);
        }
        // Decoding the gif may fail even if the type matches.
        if (result == null) {
            // We can only reset the buffered InputStream, so to start from the beginning of the stream, we need to
            // pass in a new source containing the buffered stream rather than the original stream.
            ImageVideoWrapper forBitmapDecoder = new ImageVideoWrapper(bis, source.getFileDescriptor());
            result = decodeBitmapWrapper(forBitmapDecoder, width, height);
        }
        return result;
    }

    private GifBitmapWrapper decodeBitmapWrapper(ImageVideoWrapper toDecode, int width, int height) throws IOException {
        GifBitmapWrapper result = null;

        Resource<Bitmap> bitmapResource = bitmapDecoder.decode(toDecode, width, height);
        if (bitmapResource != null) {
            result = new GifBitmapWrapper(bitmapResource, null);
        }

        return result;
    }
    decodeStream 会判断是不是 Gif , 如果不是 Gif 会调用 decodeBitmapWrapper 方法,这个时候会调用 bitmapDecoder.decode() 方法,这个方法应该要去处理图片了?
   真正解析Bitmap:
  @Override
      public Resource<Bitmap> decode(InputStream source, int width, int height) {
          Bitmap bitmap = downsampler.decode(source, bitmapPool, width, height, decodeFormat);
          return BitmapResource.obtain(bitmap, bitmapPool);
      }

      public Bitmap decode(InputStream is, BitmapPool pool, int outWidth, int outHeight, DecodeFormat decodeFormat) {
          final ByteArrayPool byteArrayPool = ByteArrayPool.get();
          final byte[] bytesForOptions = byteArrayPool.getBytes();
          final byte[] bytesForStream = byteArrayPool.getBytes();
          final BitmapFactory.Options options = getDefaultOptions();

          // Use to fix the mark limit to avoid allocating buffers that fit entire images.
          RecyclableBufferedInputStream bufferedStream = new RecyclableBufferedInputStream(
                  is, bytesForStream);
          // Use to retrieve exceptions thrown while reading.
          // TODO(#126): when the framework no longer returns partially decoded Bitmaps or provides a way to determine
          // if a Bitmap is partially decoded, consider removing.
          ExceptionCatchingInputStream exceptionStream =
                  ExceptionCatchingInputStream.obtain(bufferedStream);
          // Use to read data.
          // Ensures that we can always reset after reading an image header so that we can still attempt to decode the
          // full image even when the header decode fails and/or overflows our read buffer. See #283.
          MarkEnforcingInputStream invalidatingStream = new MarkEnforcingInputStream(exceptionStream);
          try {
              exceptionStream.mark(MARK_POSITION);
              int orientation = 0;
              try {
                  orientation = new ImageHeaderParser(exceptionStream).getOrientation();
              } catch (IOException e) {
                  if (Log.isLoggable(TAG, Log.WARN)) {
                      Log.w(TAG, "Cannot determine the image orientation from header", e);
                  }
              } finally {
                  try {
                      exceptionStream.reset();
                  } catch (IOException e) {
                      if (Log.isLoggable(TAG, Log.WARN)) {
                          Log.w(TAG, "Cannot reset the input stream", e);
                      }
                  }
              }

              options.inTempStorage = bytesForOptions;

              final int[] inDimens = getDimensions(invalidatingStream, bufferedStream, options);
              final int inWidth = inDimens[0];
              final int inHeight = inDimens[1];

              final int degreesToRotate = TransformationUtils.getExifOrientationDegrees(orientation);
              final int sampleSize = getRoundedSampleSize(degreesToRotate, inWidth, inHeight, outWidth, outHeight);

              final Bitmap downsampled =
                      downsampleWithSize(invalidatingStream, bufferedStream, options, pool, inWidth, inHeight, sampleSize,
                              decodeFormat);

              // BitmapFactory swallows exceptions during decodes and in some cases when inBitmap is non null, may catch
              // and log a stack trace but still return a non null bitmap. To avoid displaying partially decoded bitmaps,
              // we catch exceptions reading from the stream in our ExceptionCatchingInputStream and throw them here.
              final Exception streamException = exceptionStream.getException();
              if (streamException != null) {
                  throw new RuntimeException(streamException);
              }

              Bitmap rotated = null;
              if (downsampled != null) {
                  rotated = TransformationUtils.rotateImageExif(downsampled, pool, orientation);

                  if (!downsampled.equals(rotated) && !pool.put(downsampled)) {
                      downsampled.recycle();
                  }
              }

              return rotated;
          } finally {
              byteArrayPool.releaseBytes(bytesForOptions);
              byteArrayPool.releaseBytes(bytesForStream);
              exceptionStream.release();
              releaseOptions(options);
          }
      }
      就是从 InputStream 中去获取 Bitmap 对象,这些代码还是比较容易看懂的,Downsampler.decode() 返回的是一个 Bitmap 对象,StreamBitmapDecoder.decode() 对 Bitmap 又进行了一层包裹,返回的是 BitmapResource 。接下来我们回到 GifBitmapWrapperResourceDecoder.decode 中返回的是 GifBitmapWrapperResource , 接着往回走就回到了 DecodeJob.transformEncodeAndTranscode() 中:
      private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {
              long startTime = LogTime.getLogTime();
              Resource<T> transformed = transform(decoded);
              if (Log.isLoggable(TAG, Log.VERBOSE)) {
                  logWithTimeAndKey("Transformed resource from source", startTime);
              }

              writeTransformedToCache(transformed);

              startTime = LogTime.getLogTime();
              Resource<Z> result = transcode(transformed);
              if (Log.isLoggable(TAG, Log.VERBOSE)) {
                  logWithTimeAndKey("Transcoded transformed from source", startTime);
              }
              return result;
          }

          private Resource<T> transform(Resource<T> decoded) {
              if (decoded == null) {
                  return null;
              }

              Resource<T> transformed = transformation.transform(decoded, width, height);
              if (!decoded.equals(transformed)) {
                  decoded.recycle();
              }
              return transformed;
          }

          private Resource<Z> transcode(Resource<T> transformed) {
              if (transformed == null) {
                  return null;
              }
              return transcoder.transcode(transformed);
          }

      上面主要分为三步,transform(),writeTransformedToCache() 写入缓存,transcode() 这里要注意了是把 泛型 T 转成了 Z 。transcode() 方法中又是调用了 transcoder 的 transcode() 方法,发现又找不到代码了,所以我们有得回去找 transcoder 实现类,这也是说我们为什么最好要会画 UML 图,因为代码架构复杂的情况下,我们在里面游几天都上不来。还是回去找找,是在第二步 load 的时候创建的 glide.buildTranscoder(resourceClass, transcodedClass)  是 GifBitmapWrapperDrawableTranscoder :
          @SuppressWarnings("unchecked")
          @Override
          public Resource<GlideDrawable> transcode(Resource<GifBitmapWrapper> toTranscode) {
              GifBitmapWrapper gifBitmap = toTranscode.get();
              Resource<Bitmap> bitmapResource = gifBitmap.getBitmapResource();

              final Resource<? extends GlideDrawable> result;
              if (bitmapResource != null) {
                  result = bitmapDrawableResourceTranscoder.transcode(bitmapResource);
              } else {
                  result = gifBitmap.getGifResource();
              }
              // This is unchecked but always safe, anything that extends a Drawable can be safely cast to a Drawable.
              return (Resource<GlideDrawable>) result;
          }

          @Override
          public Resource<GlideBitmapDrawable> transcode(Resource<Bitmap> toTranscode) {
              GlideBitmapDrawable drawable = new GlideBitmapDrawable(resources, toTranscode.get());
              return new GlideBitmapDrawableResource(drawable, bitmapPool);
          }

      这里主要是把 GifBitmapWrapper 转成了 GlideDrawable ,为什么这么弄肯定是为了后面方便显示,因为 Gif 资源返回的已经是 GifDrawable 了并不需要转换,而图片资源返回的是 Bitmap ,做一次转换之后统一转成 GlideBitmapDrawable 这样方便后面做显示。
      最后就是回到onLoadComplete中,显示图片,简单说一下, 最终调用了 target 的 onResourceReady() 方法,那么 target 又是谁呢?不知道我们是否还记得这代码into(glide.buildImageViewTarget(view, transcodeClass)) 在之前就分析过的 GlideDrawableImageViewTarget :
          @Override
          public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
              if (!resource.isAnimated()) {
                  //TODO: Try to generalize this to other sizes/shapes.
                  // This is a dirty hack that tries to make loading square thumbnails and then square full images less costly
                  // by forcing both the smaller thumb and the larger version to have exactly the same intrinsic dimensions.
                  // If a drawable is replaced in an ImageView by another drawable with different intrinsic dimensions,
                  // the ImageView requests a layout. Scrolling rapidly while replacing thumbs with larger images triggers
                  // lots of these calls and causes significant amounts of jank.
                  float viewRatio = view.getWidth() / (float) view.getHeight();
                  float drawableRatio = resource.getIntrinsicWidth() / (float) resource.getIntrinsicHeight();
                  if (Math.abs(viewRatio - 1f) <= SQUARE_RATIO_MARGIN
                          && Math.abs(drawableRatio - 1f) <= SQUARE_RATIO_MARGIN) {
                      resource = new SquaringDrawable(resource, view.getWidth());
                  }
              }
              super.onResourceReady(resource, animation);
              this.resource = resource;
              resource.setLoopCount(maxLoopCount);
              resource.start();
          }
      
          @Override
          public void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) {
              if (glideAnimation == null || !glideAnimation.animate(resource, this)) {
                  setResource(resource);
              }
          }
      
          @Override
          protected void setResource(GlideDrawable resource) {
              view.setImageDrawable(resource);
          }
      
   现在我们来总结一下 decode() 方法都干了啥,首先是 DecodeJob.decodeFromSource()
      -> fetcher.loadData() 去联网获取 InputStream
       -> loadProvider.getSourceDecoder().decode()
       -> bitmapDecoder.decode() 解析 InputStream  压缩旋转等等返回 Bitmap
       -> DecodeJob.transformEncodeAndTranscode() 去转换保证返回数据一致 GlideDrawable 。
       最后一步,接下来只需要看下 onLoadComplete , 最终调用了 target 的 onResourceReady() 方法,那么 target 又是谁呢?不知道我们是否还记得这代码into(glide.buildImageViewTarget(view, transcodeClass)) 在之前就分析过的 GlideDrawableImageViewTarget :

          @Override
          protected void setResource(GlideDrawable resource) {
              view.setImageDrawable(resource);
          }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值