Glide源码分析之加载图片URL

藏宝库编辑 2024-9-28 12:56:29 107 0 来自 中国
简介

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

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

@NonNullpublic static RequestManager with(@NonNull Context context) { //etRetriever()  获取RequestManagerRetriever return getRetriever(context).get(context);} @NonNullpublic RequestManager get(@NonNull Context context) { if (context == null) {   throw new IllegalArgumentException("You cannot start a load on a null Context"); } else if (Util.isOnMainThread() && !(context instanceof Application)) {   if (context instanceof FragmentActivity) {     return get((FragmentActivity) context);   } else if (context instanceof Activity) {     return get((Activity) context);   } else if (context instanceof ContextWrapper) {     return get(((ContextWrapper) context).getBaseContext());   } } return getApplicationManager(context);}Glide.with(context) --> (RequestManagerRetriever)getRetriever(context).get(context)-->(RequestManagerRetriever)getApplicationManager(context){    //初始化 Glide    Glide glide = Glide.get(context.getApplicationContext());    //初始化 RequestManager       applicationManager =           factory.build(               glide,               new ApplicationLifecycle(),               new EmptyRequestManagerTreeNode(),               context.getApplicationContext());     }}//创建 RequestManager public interface RequestManagerFactory { @NonNull RequestManager build(     @NonNull Glide glide,     @NonNull Lifecycle lifecycle,     @NonNull RequestManagerTreeNode requestManagerTreeNode,     @NonNull Context context);}//创建 RequestManagerprivate static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() { @NonNull @Override public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,     @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {   return new RequestManager(glide, lifecycle, requestManagerTreeNode, context); }};}1.2  Glide.get(context.getApplicationContext())

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

load()方法默认是 asRrawable()类型,用来初始化RequestBuilder 和 loadGeneric()方法初始化model(地址)
注意
这里体现了 asBitmap()和asDrawable() 方法必须放在load()前边的原因
//as方法@NonNull@CheckResult@Overridepublic RequestBuilder<Drawable> load(@Nullable String string) { return asDrawable().load(string);}@NonNull@CheckResultpublic RequestBuilder<Drawable> asDrawable() { return as(Drawable.class);}//(重要) 创建了 RequestBuilder  且 默认传入的 resourceClass  是  Drawable.class)//返回 获取target DrawableImageViewTarget @NonNull@CheckResultpublic <ResourceType> RequestBuilder<ResourceType> as(   @NonNull Class<ResourceType> resourceClass) { return new RequestBuilder<>(glide, this, resourceClass, context);}//设置加载的内容(地址或者资源  ) /*** Sets the specific model to load data for.** @param model The model to load data for, or null.* @return This request builder.*/@NonNull@CheckResult@SuppressWarnings("unchecked")@Overridepublic RequestBuilder<TranscodeType> load(@Nullable Object model) { return loadGeneric(model);}@NonNullprivate RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) { this.model = model; isModelSet = true; return this;}3.Glide 的into() 资源选择以及下载都在这里这里重点分析

1.调用into方法()

//调用into()方法  @NonNullpublic ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {  Util.assertMainThread();  Preconditions.checkNotNull(view);  //设置 RequestOptions 参数  RequestOptions requestOptions = this.requestOptions;  if (!requestOptions.isTransformationSet()      && requestOptions.isTransformationAllowed()      && view.getScaleType() != null) {    // Clone in this method so that if we use this RequestBuilder to load into a View and then    // into a different target, we don't retain the transformation applied based on the previous    // View's scale type.    switch (view.getScaleType()) {      case CENTER_CROP:        requestOptions = requestOptions.clone().optionalCenterCrop();        break;      case CENTER_INSIDE:        requestOptions = requestOptions.clone().optionalCenterInside();        break;      case FIT_CENTER:      case FIT_START:      case FIT_END:        requestOptions = requestOptions.clone().optionalFitCenter();        break;      case FIT_XY:        requestOptions = requestOptions.clone().optionalCenterInside();        break;      case CENTER:      case MATRIX:      default:        // Do nothing.    }  }      //获取 ViewTarget 类型  默认得到DrawableImageViewTarget  因为load方法默认调用 asDrawable()      glideContext.buildImageViewTarget(view, transcodeClass)        return into(      glideContext.buildImageViewTarget(view, transcodeClass),      /*targetListener=*/ null,      requestOptions);}//继续调用  private <Y extends Target<TranscodeType>> Y into(    @NonNull Y target,    @Nullable RequestListener<TranscodeType> targetListener,    @NonNull RequestOptions options) {    //判断主线程  Preconditions.checkNotNull(target);  if (!isModelSet) {    throw new IllegalArgumentException("You must call #load() before calling #into()");  }  options = options.autoClone();  //构建请求  核心方法  Request request = buildRequest(target, targetListener, options);  Request previous = target.getRequest();  if (request.isEquivalentTo(previous)      && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {    request.recycle();       if (!Preconditions.checkNotNull(previous).isRunning()) {           previous.begin();    }    return target;  }  requestManager.clear(target);  target.setRequest(request);  requestManager.track(target, request);  return target;}1.2.构建请求(RequestBuilder 请求构建类)

//  调用构建请求RequestBuilder 的构建方法private Request buildRequest(    Target<TranscodeType> target,    @Nullable RequestListener<TranscodeType> targetListener,    RequestOptions requestOptions) {  return buildRequestRecursive(      target,      targetListener,      /*parentCoordinator=*/ null,      transitionOptions,      requestOptions.getPriority(),      requestOptions.getOverrideWidth(),      requestOptions.getOverrideHeight(),      requestOptions);}private Request buildRequestRecursive(    Target<TranscodeType> target,    @Nullable RequestListener<TranscodeType> targetListener,    @Nullable RequestCoordinator parentCoordinator,    TransitionOptions<?, ? super TranscodeType> transitionOptions,    Priority priority,    int overrideWidth,    int overrideHeight,    RequestOptions requestOptions) {  // Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.  ErrorRequestCoordinator errorRequestCoordinator = null;    //判断错误的构建是否存在,这里第一次不执行  if (errorBuilder != null) {    errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);    parentCoordinator = errorRequestCoordinator;  }      //执行构建主要的请求  Request mainRequest =      buildThumbnailRequestRecursive(          target,          targetListener,          parentCoordinator,          transitionOptions,          priority,          overrideWidth,          overrideHeight,          requestOptions);  if (errorRequestCoordinator == null) {    return mainRequest;  }  int errorOverrideWidth = errorBuilder.requestOptions.getOverrideWidth();  int errorOverrideHeight = errorBuilder.requestOptions.getOverrideHeight();  if (Util.isValidDimensions(overrideWidth, overrideHeight)      && !errorBuilder.requestOptions.isValidOverride()) {    errorOverrideWidth = requestOptions.getOverrideWidth();    errorOverrideHeight = requestOptions.getOverrideHeight();  }  Request errorRequest = errorBuilder.buildRequestRecursive(      target,      targetListener,      errorRequestCoordinator,      errorBuilder.transitionOptions,      errorBuilder.requestOptions.getPriority(),      errorOverrideWidth,      errorOverrideHeight,      errorBuilder.requestOptions);  errorRequestCoordinator.setRequests(mainRequest, errorRequest);  return errorRequestCoordinator;}    //执行构建主要的请求 private Request buildThumbnailRequestRecursive(    Target<TranscodeType> target,    RequestListener<TranscodeType> targetListener,    @Nullable RequestCoordinator parentCoordinator,    TransitionOptions<?, ? super TranscodeType> transitionOptions,    Priority priority,    int overrideWidth,    int overrideHeight,    RequestOptions requestOptions) {    //第一次为空  if (thumbnailBuilder != null) {    // Recursive case: contains a potentially recursive thumbnail request builder.    if (isThumbnailBuilt) {      throw new IllegalStateException("You cannot use a request as both the main request and a "          + "thumbnail, consider using clone() on the request(s) passed to thumbnail()");    }    TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =        thumbnailBuilder.transitionOptions;    // Apply our transition by default to thumbnail requests but avoid overriding custom options    // that may have been applied on the thumbnail request explicitly.    if (thumbnailBuilder.isDefaultTransitionOptionsSet) {      thumbTransitionOptions = transitionOptions;    }    Priority thumbPriority = thumbnailBuilder.requestOptions.isPrioritySet()        ? thumbnailBuilder.requestOptions.getPriority() : getThumbnailPriority(priority);    int thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();    int thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();    if (Util.isValidDimensions(overrideWidth, overrideHeight)        && !thumbnailBuilder.requestOptions.isValidOverride()) {      thumbOverrideWidth = requestOptions.getOverrideWidth();      thumbOverrideHeight = requestOptions.getOverrideHeight();    }    ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);    Request fullRequest =        obtainRequest(            target,            targetListener,            requestOptions,            coordinator,            transitionOptions,            priority,            overrideWidth,            overrideHeight);    isThumbnailBuilt = true;    // Recursively generate thumbnail requests.    Request thumbRequest =        thumbnailBuilder.buildRequestRecursive(            target,            targetListener,            coordinator,            thumbTransitionOptions,            thumbPriority,            thumbOverrideWidth,            thumbOverrideHeight,            thumbnailBuilder.requestOptions);    isThumbnailBuilt = false;    coordinator.setRequests(fullRequest, thumbRequest);    return coordinator;  } else if (thumbSizeMultiplier != null) {    // Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.    ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);    Request fullRequest =        obtainRequest(            target,            targetListener,            requestOptions,            coordinator,            transitionOptions,            priority,            overrideWidth,            overrideHeight);    RequestOptions thumbnailOptions = requestOptions.clone()        .sizeMultiplier(thumbSizeMultiplier);    Request thumbnailRequest =        obtainRequest(            target,            targetListener,            thumbnailOptions,            coordinator,            transitionOptions,            getThumbnailPriority(priority),            overrideWidth,            overrideHeight);    coordinator.setRequests(fullRequest, thumbnailRequest);    return coordinator;  } else {    // Base case: no thumbnail.        // 第一次为空直接执行    return obtainRequest(        target,        targetListener,        requestOptions,        parentCoordinator,        transitionOptions,        priority,        overrideWidth,        overrideHeight);  }}  //获取请求private Request obtainRequest(    Target<TranscodeType> target,    RequestListener<TranscodeType> targetListener,    RequestOptions requestOptions,    RequestCoordinator requestCoordinator,    TransitionOptions<?, ? super TranscodeType> transitionOptions,    Priority priority,    int overrideWidth,    int overrideHeight) {  return SingleRequest.obtain(      context,      glideContext,      model,      transcodeClass,      requestOptions,      overrideWidth,      overrideHeight,      priority,      target,      targetListener,      requestListener,      requestCoordinator,      glideContext.getEngine(),      transitionOptions.getTransitionFactory());}// SingleRequest 单例请求类  public static <R> SingleRequest<R> obtain(    Context context,    GlideContext glideContext,    Object model,    Class<R> transcodeClass,    RequestOptions requestOptions,    int overrideWidth,    int overrideHeight,    Priority priority,    Target<R> target,    RequestListener<R> targetListener,    RequestListener<R> requestListener,    RequestCoordinator requestCoordinator,    Engine engine,    TransitionFactory<? super R> animationFactory) {  @SuppressWarnings("unchecked") SingleRequest<R> request =      (SingleRequest<R>) POOL.acquire();  if (request == null) {    request = new SingleRequest<>();  }  request.init(      context,      glideContext,      model,      transcodeClass,      requestOptions,      overrideWidth,      overrideHeight,      priority,      target,      targetListener,      requestListener,      requestCoordinator,      engine,      animationFactory);  return request;}//初始化单例 请求rivate void init(    Context context,    GlideContext glideContext,    Object model,    Class<R> transcodeClass,    RequestOptions requestOptions,    int overrideWidth,    int overrideHeight,    Priority priority,    Target<R> target,    RequestListener<R> targetListener,    RequestListener<R> requestListener,    RequestCoordinator requestCoordinator,    Engine engine,    TransitionFactory<? super R> animationFactory) {  this.context = context;  this.glideContext = glideContext;  this.model = model;  this.transcodeClass = transcodeClass;  this.requestOptions = requestOptions;  this.overrideWidth = overrideWidth;  this.overrideHeight = overrideHeight;  this.priority = priority;  this.target = target;  this.targetListener = targetListener;  this.requestListener = requestListener;  this.requestCoordinator = requestCoordinator;  this.engine = engine;  this.animationFactory = animationFactory;  status = Status.PENDING;}1.3 开启请求

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

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

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

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

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

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

这里简单的梳理了Glide 第一次加载图片 从初始化到配置参数,然后判断是否有缓存再到下载完成然后通知展示的简单流程.源码中涉及到的回调比较多建议代码跟一下(特别注意生命周期的影响).
大致上代码流程是:
Glide.with()配置Glide 的一些参数 load() 配置请求的构建起 into()首先判断本子资源是否有然后缓存文件是否存在都没有就调用下载,下载完成通知展示.因为Glide RequestManager implements LifecycleListener 监听了页面的生命周期注意,一下生命周期对展示的影响
还有一些生命周期对Glide的影响,以及异常展示的流程没有处理,有兴趣的可以研究下
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 18:19, Processed in 0.200788 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表