Android主流三方库源码分析(三、深入理解Glide源码)

Android主流三方库源码分析(三、深入理解Glide源码),第1张

概述相关文章https://www.cnblogs.com/billshen/p/13306285.htmlhttps://blog.csdn.net/songzi1228/article/details/84426165一、基本使用流程Glide最基本的使用流程就是下面这行代码,其它所有扩展的额外功能都是以其建造者链式调用的基础上增加的。GlideApp.with(context).loa 相关文章

https://www.cnblogs.com/billshen/p/13306285.html

https://blog.csdn.net/songzi1228/article/details/84426165

一、基本使用流程

GlIDe最基本的使用流程就是下面这行代码,其它所有扩展的额外功能都是以其建造者链式调用的基础上增加的。

GlIDeApp.with(context).load(url).into(iv);复制代码

GlIDe全部的方法: 

GlIDe.with(getApplicationContext()) // 指定Context                .load(url)// 指定图片的URL                .placeholder(R.mipmap.ic_launcher)// 指定图片未成功加载前显示的图片                .error(R.mipmap.ic_launcher)// 指定图片加载失败显示的图片                .overrIDe(300, 300)//指定图片的尺寸                .fitCenter()//指定图片缩放类型为                .centerCrop()// 指定图片缩放类型为                .skipMemoryCache(true)// 跳过内存缓存,不包括磁盘缓存                .diskCacheStrategy(diskCacheStrategy.NONE)//跳过磁盘缓存                .diskCacheStrategy(diskCacheStrategy.soURCE)//仅仅只缓存原来的全分辨率的图像                .diskCacheStrategy(diskCacheStrategy.RESulT)//仅仅缓存最终的图像                .diskCacheStrategy(diskCacheStrategy.ALL)//缓存所有版本的图像                .priority(Priority.HIGH)//指定优先级.GlIDe将会用他们作为一个准则,//并尽可能的处理这些请求,                // 但是它不能保证所有的图片都会按照所要求的顺序加载。优先级排序:                //IMMEDIATE > HIGH > norMAL > LOW                .into(imageVIEw);//指定显示图片的ImagevIEw

其中的GlIDeApp是注解处理器自动生成的,要使用GlIDeApp,必须先配置应用的AppGlIDeModule模块,里面可以为空配置,也可以根据实际情况添加指定配置。

@GlIDeModulepublic class MyAppGlIDeModule extends AppGlIDeModule {    @OverrIDe    public voID applyOptions(Context context, GlIDeBuilder builder) {        // 实际使用中根据情况可以添加如下配置        <!--builder.setDefaultRequestoptions(new Requestoptions().format(DecodeFormat.PREFER_RGB_565));-->        <!--int memoryCacheSizeBytes = 1024 * 1024 * 20;-->        <!--builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes));-->        <!--int bitmapPoolSizeBytes = 1024 * 1024 * 30;-->        <!--builder.setBitmapPool(new LruBitmapPool(bitmapPoolSizeBytes));-->        <!--int diskCacheSizeBytes = 1024 * 1024 * 100;-->        <!--builder.setdiskCache(new InternalCachediskCacheFactory(context, diskCacheSizeBytes));-->    }}复制代码

接下来,本文将针对GlIDe的最新源码版本V4.8.0对GlIDe加载网络图片的流程进行详细地分析与讲解,力争做到让读者朋友们知其然也知其所以然。

二、GlIDeApp.with(context)源码详解

首先,用艽野尘梦绘制的这份GlIDe框架图让我们对GlIDe的总体框架有一个初步的了解。

从GlIDeApp.with这行代码开始,内部主线执行流程如下。

1、GlIDeApp#with

return (GlIDeRequests) GlIDe.with(context);复制代码

2、GlIDe#with

return getRetrIEver(context).get(context);return GlIDe.get(context).getRequestManagerRetrIEver();// 外部使用了双重检锁的同步方式确保同一时刻只执一次GlIDe的初始化checkAndInitializeGlIDe(context);initializeGlIDe(context);// 最终执行到GlIDe的另一个重载方法initializeGlIDe(context, new GlIDeBuilder());@SuppressWarnings("deprecation")  private static voID initializeGlIDe(@NonNull Context   context, @NonNull GlIDeBuilder builder) {    Context applicationContext =     context.getApplicationContext();    // 1、获取前面应用中带注解的GlIDeModule    GeneratedAppGlIDeModule annotationGeneratedModule =     getAnnotationGeneratedGlIDeModules();    // 2、如果GlIDeModule为空或者可配置manifest里面的标志为true,则获取manifest里面    // 配置的GlIDeModule模块(manifestModules)。    List<com.bumptech.glIDe.module.GlIDeModule>     manifestModules = Collections.emptyList();    if (annotationGeneratedModule == null ||     annotationGeneratedModule.isManifestParsingEnabled(    )) {      manifestModules = new   ManifestParser(applicationContext).parse();    }    ...    RequestManagerRetrIEver.RequestManagerFactory     factory =        annotationGeneratedModule != null            ? annotationGeneratedModule.getRequestManag    erFactory() : null;    builder.setRequestManagerFactory(factory);    for (com.bumptech.glIDe.module.GlIDeModule module :     manifestModules) {      module.applyOptions(applicationContext, builder);    }    if (annotationGeneratedModule != null) {      annotationGeneratedModule.applyOptions(applicatio  nContext, builder);    }    // 3、初始化各种配置信息    GlIDe glIDe = builder.build(applicationContext);    // 4、把manifestModules以及annotationGeneratedModule里面的配置信息放到builder    // 里面(applyOptions)替换glIDe默认组件(registerComponents)    for (com.bumptech.glIDe.module.GlIDeModule module :     manifestModules) {      module.registerComponents(applicationContext,   glIDe, glIDe.registry);    }    if (annotationGeneratedModule != null) {      annotationGeneratedModule.registerComponents(appl  icationContext, glIDe, glIDe.registry);    }    applicationContext.registerComponentCallbacks(glIDe    );    GlIDe.glIDe = glIDe;}复制代码

3、GlIDeBuilder#build

@NonNull  GlIDe build(@NonNull Context context) {    // 创建请求图片线程池sourceExecutor    if (sourceExecutor == null) {      sourceExecutor =   GlIDeExecutor.newSourceExecutor();    }    // 创建硬盘缓存线程池diskCacheExecutor    if (diskCacheExecutor == null) {      diskCacheExecutor =   GlIDeExecutor.newdiskCacheExecutor();    }    // 创建动画线程池animationExecutor    if (animationExecutor == null) {      animationExecutor =   GlIDeExecutor.newAnimationExecutor();    }    if (memorySizeCalculator == null) {      memorySizeCalculator = new   MemorySizeCalculator.Builder(context).build();    }    if (connectivityMonitorFactory == null) {      connectivityMonitorFactory = new   DefaultConnectivityMonitorFactory();    }    if (bitmapPool == null) {      // 依据设备的屏幕密度和尺寸设置各种pool的size      int size =   memorySizeCalculator.getBitmapPoolSize();      if (size > 0) {        // 创建图片线程池LruBitmapPool,缓存所有被释放的bitmap        // 缓存策略在API大于19时,为SizeConfigStrategy,小于为AttributeStrategy。        // 其中SizeConfigStrategy是以bitmap的size和config为key,value为bitmap的HashMap        bitmapPool = new LruBitmapPool(size);      } else {        bitmapPool = new BitmapPoolAdapter();      }    }    // 创建对象数组缓存池LruArrayPool,默认4M    if (arrayPool == null) {      arrayPool = new   LruArrayPool(memorySizeCalculator.getarraypoolsiz  eInBytes());    }    // 创建LruResourceCache,内存缓存    if (memoryCache == null) {      memoryCache = new   LruResourceCache(memorySizeCalculator.getMemoryCa  cheSize());    }    if (diskCacheFactory == null) {      diskCacheFactory = new   InternalCachediskCacheFactory(context);    }    // 创建任务和资源管理引擎(线程池,内存缓存和硬盘缓存对象)    if (engine == null) {      engine =          new Engine(              memoryCache,              diskCacheFactory,              diskCacheExecutor,              sourceExecutor,              GlIDeExecutor.newUnlimitedSourceExecutor(  ),              GlIDeExecutor.newAnimationExecutor(),              isActiveResourceRetentionAllowed);    }        RequestManagerRetrIEver requestManagerRetrIEver =    new RequestManagerRetrIEver(requestManagerFactory);    return new GlIDe(        context,        engine,        memoryCache,        bitmapPool,        arrayPool,        requestManagerRetrIEver,        connectivityMonitorFactory,        logLevel,        defaultRequestoptions.lock(),        defaultTransitionOptions);}复制代码

4、GlIDe#GlIDe构造方法

GlIDe(...) {    ...    // 注册管理任务执行对象的类(Registry)    // Registry是一个工厂,而其中所有注册的对象都是一个工厂员工,当任务分发时,    // 根据当前任务的性质,分发给相应员工进行处理    registry = new Registry();        ...        // 这里大概有60余次的append或register员工组件(解析器、编解码器、工厂类、转码类等等组件)    registry    .append(ByteBuffer.class, new ByteBufferEncoder())    .append(inputStream.class, new StreamEncoder(arrayPool))        // 根据给定子类产出对应类型的target(BitmAPImageVIEwTarget / DrawableImageVIEwTarget)    ImageVIEwTargetFactory imageVIEwTargetFactory = new ImageVIEwTargetFactory();        glIDeContext =        new GlIDeContext(            context,            arrayPool,            registry,            imageVIEwTargetFactory,            defaultRequestoptions,            defaultTransitionOptions,            engine,            logLevel);} 复制代码

5、RequestManagerRetrIEver#get

@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)) {    // 如果当前线程是主线程且context不是Application走相应的get重载方法    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());    }  }  // 否则直接将请求与Applicationlifecycle关联  return getApplicationManager(context);}复制代码

这里总结一下,对于当前传入的context是application或当前线程是子线程时,请求的生命周期和Applicationlifecycle关联,否则,context是FragmentActivity或Fragment时,在当前组件添加一个SupportFragment(SupportRequestManagerFragment),context是Activity时,在当前组件添加一个Fragment(RequestManagerFragment)。

6、GlIDeApp#with小结

1、初始化各式各样的配置信息(包括缓存,请求线程池,大小,图片格式等等)以及glIDe对象。

2、将glIDe请求和application/SupportFragment/Fragment的生命周期绑定在一块。

这里我们再回顾一下with方法的执行流程。

三、load(url)源码详解

1、GlIDeRequest(RequestManager)#load

return (GlIDeRequest<Drawable>) super.load(string);return asDrawable().load(string);// 1、asDrawable部分return (GlIDeRequest<Drawable>) super.asDrawable();return as(Drawable.class);// 最终返回了一个GlIDeRequest(RequestManager的子类)return new GlIDeRequest<>(glIDe, this, resourceClass, context);// 2、load部分return (GlIDeRequest<TranscodeType>) super.load(string);return loadGeneric(string);@NonNullprivate RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {    // model则为设置的url    this.model = model;    // 记录url已设置    isModelSet = true;    return this;}复制代码

可以看到,load这部分的源码很简单,就是给GlIDeRequest(RequestManager)设置了要请求的mode(url),并记录了url已设置的状态。

这里,我们再看看load方法的执行流程。

四、into(iv)源码详解

前方预警,真正复杂的地方开始了。

1、RequestBuilder.into

 @NonNullpublic VIEwTarget<ImageVIEw, TranscodeType>   into(@NonNull ImageVIEw vIEw) {  Util.assertMainThread();  Preconditions.checkNotNull(vIEw);  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()) {      // 这个Requestoptions里保存了要设置的scaleType,GlIDe自身封装了CenterCrop、CenterInsIDe、      // FitCenter、CenterInsIDe四种规格。      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.    }  }  // 注意,这个transcodeClass是指的drawable或bitmap  return into(      glIDeContext.buildImageVIEwTarget(vIEw,     transcodeClass),      /*targetListener=*/ null,      requestoptions);}复制代码

2、GlIDeContext#buildImageVIEwTarget

return imageVIEwTargetFactory.buildTarget(imageVIEw, transcodeClass); 复制代码

3、ImageVIEwTargetFactory#buildTarget

@NonNull@SuppressWarnings("unchecked")public <Z> VIEwTarget<ImageVIEw, Z>   buildTarget(@NonNull ImageVIEw vIEw,    @NonNull Class<Z> clazz) {  // 返回展示Bimtap/Drawable资源的目标对象  if (Bitmap.class.equals(clazz)) {    return (VIEwTarget<ImageVIEw, Z>) new   BitmAPImageVIEwTarget(vIEw);  } else if (Drawable.class.isAssignableFrom(clazz))     {    return (VIEwTarget<ImageVIEw, Z>) new   DrawableImageVIEwTarget(vIEw);  } else {    throw new IllegalArgumentException(        "Unhandled class: " + clazz + ", try   .as*(Class).transcode(ResourceTranscoder)");  }}复制代码

可以看到,GlIDe内部只维护了两种target,一种是BitmAPImageVIEwTarget,另一种则是DrawableImageVIEwTarget,接下来继续深入。

4、RequestBuilder#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();    // 分析1.建立请求    Request request = buildrequest(target,     targetListener, options);    Request prevIoUs = target.getRequest();    if (request.isEquivalentTo(prevIoUs)        && !isSkipMemoryCacheWithCompletePrevIoUsReques    t(options, prevIoUs)) {      request.recycle();      // If the request is completed, beginning again   will ensure the result is re-delivered,      // triggering RequestListeners and Targets. If   the request is Failed, beginning again will      // restart the request, giving it another chance   to complete. If the request is already      // running, we can let it continue running   without interruption.      if (!Preconditions.checkNotNull(prevIoUs).isRunni  ng()) {        // Use the prevIoUs request rather than the new     one to allow for optimizations like skipPing        // setting placeholders, tracking and     un-tracking Targets, and obtaining VIEw     dimensions        // that are done in the indivIDual Request.        prevIoUs.begin();      }      return target;    }        requestManager.clear(target);    target.setRequest(request);    // 分析2.真正追踪请求的地方    requestManager.track(target, request);    return target;}// 分析1private 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);}// 分析1private 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(异常处理对象)      errorRequestCoordinator = new   ErrorRequestCoordinator(parentCoordinator);      parentCoordinator = errorRequestCoordinator;    }    // 递归建立缩略图请求    Request mainRequest =        buildthumbnailRequestRecursive(            target,            targetListener,            parentCoordinator,            TransitionOptions,            priority,            overrIDeWIDth,            overrIDeHeight,            requestoptions);    if (errorRequestCoordinator == null) {      return mainRequest;    }    ...        Request errorRequest =     errorBuilder.buildrequestRecursive(        target,        targetListener,        errorRequestCoordinator,        errorBuilder.TransitionOptions,        errorBuilder.requestoptions.getPriority(),        errorOverrIDeWIDth,        errorOverrIDeHeight,        errorBuilder.requestoptions);    errorRequestCoordinator.setRequests(mainRequest,     errorRequest);    return errorRequestCoordinator;}// 分析1private 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.            ...      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(thumbnailRequestCoordinator)是作为两者的协调者,      // 能够同时加载缩略图和正常的图的请求      coordinator.setRequests(fullRequest, thumbRequest);      return coordinator;    } else if (thumbSizeMultiplIEr != null) {      // Base case: thumbnail multiplIEr generates a thumbnail request, but cannot recurse.      // 当设置了缩略的比例thumbSizeMultiplIEr(0 ~  1)时,      // 不需要递归建立缩略图请求      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) {    // 最终实际返回的是一个SingleRequest对象(将制定的资源加载进对应的Target    return SingleRequest.obtain(        context,        glIDeContext,        model,        transcodeClass,        requestoptions,        overrIDeWIDth,        overrIDeHeight,        priority,        target,        targetListener,        requestListeners,        requestCoordinator,        glIDeContext.getEngine(),        TransitionOptions.getTransitionFactory());}复制代码

从上源码分析可知,我们在分析1处的buildrequest()方法里建立了请求,且最多可同时进行缩略图和正常图的请求,最后,调用了requestManager.track(target, request)方法,接着看看track里面做了什么。

5、RequestManager#track

// 分析2voID track(@NonNull Target<?> target, @NonNull Request request) {    // 加入一个target目标集合(Set)    targetTracker.track(target);        requestTracker.runRequest(request);}复制代码

6、RequestTracker#runRequest

/*** Starts tracking the given request.*/// 分析2public 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");      }      // 否则清空请求,加入延迟请求队列(为了对这些请求维持一个强引用,使用了ArrayList实现)      pendingRequests.add(request);    }}复制代码

7、SingleRequest#begin

// 分析2@OverrIDepublic voID begin() {    ...    if (model == null) {      ...    // model(url)为空,回调加载失败    onl oadFailed(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;  }  status = Status.WAITING_FOR_SIZE;  if (Util.isValIDDimensions(overrIDeWIDth, overrIDeHeight)) {    // 当使用overrIDe() API为图片指定了一个固定的宽高时直接执行onSizeReady,    // 最终的核心处理位于onSizeReady    onSizeReady(overrIDeWIDth, overrIDeHeight);  } else {    // 根据imageVIEw的宽高算出图片的宽高,最终也会走到onSizeReady    target.getSize(this);  }  if ((status == Status.RUNNING || status ==     Status.WAITING_FOR_SIZE)      && canNotifyStatusChanged()) {    // 预先加载设置的缩略图    target.onLoadStarted(getPlaceholderDrawable());  }  if (IS_VERBOSE_LOGGABLE) {    logV("finished run method in " +   LogTime.getElapsedMillis(startTime));  }}复制代码

从requestManager.track(target, request)开始,最终会执行到SingleRequest#begin()方法的onSizeReady,可以猜到(因为后面只做了预加载缩略图的处理),真正的请求就是从这里开始的,咱们进去一探究竟~

8、SingleRequest#onSizeReady

// 分析2@OverrIDepublic voID onSizeReady(int wIDth, int height) {  stateVerifIEr.throwIfRecycled();    ...    status = Status.RUNNING;  float sizeMultiplIEr =     requestoptions.getSizeMultiplIEr();  this.wIDth = maybeApplySizeMultiplIEr(wIDth,     sizeMultiplIEr);  this.height = maybeApplySizeMultiplIEr(height,     sizeMultiplIEr);  ...    // 根据给定的配置进行加载,engine是一个负责加载、管理活跃和缓存资源的引擎类  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.getUseUnlimitedSourceGeneratorsP    ool(),      requestoptions.getUseAnimationPool(),      requestoptions.getonlyRetrIEveFromCache(),      this);  ...}复制代码

终于看到Engine类了,感觉距离成功不远了,继续~

9、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) {    ...  // 先从弱引用中查找,如果有的话回调onResourceReady并直接返回  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;  }  // 没有再从内存中查找,有的话会取出并放到ActiveResources(内部维护的弱引用缓存map)里面  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(decodejob的回调类,管理下载过程以及状态)  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内部维护的HashMap中  jobs.put(key, engineJob);  // 关注点8 后面分析会用到  // 注册ResourceCallback接口  engineJob.addCallback(cb);  // 内部开启线程去请求  engineJob.start(decodeJob);  if (VERBOSE_IS_LOGGABLE) {    logWithTimeAndKey("Started new load", startTime,   key);  }  return new LoadStatus(cb, engineJob);}public voID start(DecodeJob<R> decodeJob) {    this.decodeJob = decodeJob;    // willDecodeFromCache方法内部根据不同的阶段stage,如果是RESOURCE_CACHE/DATA_CACHE则返回true,使用diskCacheExecutor,否则调用getActiveSourceExecutor,内部会根据相应的条件返回sourceUnlimitedExecutor/animationExecutor/sourceExecutor    GlIDeExecutor executor =       decodeJob.willDecodeFromCache()        ? diskCacheExecutor        : getActiveSourceExecutor();    executor.execute(decodeJob);}复制代码

可以看到,最终Engine(引擎)类内部会执行到自身的start方法,它会根据不同的配置采用不同的线程池使用diskCacheExecutor/sourceUnlimitedExecutor/animationExecutor/sourceExecutor来执行最终的解码任务decodeJob。

10、DecodeJob#run

runWrapped();private voID runWrapped() {    switch (runReason) {      case INITIAliZE:        stage = getNextStage(Stage.INITIAliZE);        // 关注点1        currentGenerator = getNextGenerator();        // 关注点2 内部会调用相应Generator的startNext()        runGenerators();        break;      case SWITCH_TO_SOURCE_SERVICE:        runGenerators();        break;      case DECODE_DATA:        // 关注点3 将获取的数据解码成对应的资源        decodeFromretrIEvedData();        break;      default:        throw new IllegalStateException("Unrecognized     run reason: " + runReason);    }}// 关注点1,完整情况下,会异步依次生成这里的ResourceCacheGenerator、DataCacheGenerator和SourceGenerator对象,并在之后执行其中的startNext()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);    }}复制代码

11、SourceGenerator#startNext

// 关注点2@OverrIDepublic 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()) {    // 关注点4 getLoadData()方法内部会在modelLoaders里面找到ModelLoder对象    // (每个Generator对应一个ModelLoader),    // 并使用modelLoader.buildLoadData方法返回一个loadData列表    loadData =   helper.getLoadData().get(loadDataListIndex++);    if (loadData != null        && (helper.getdiskCacheStrategy().isDataCache  able(loadData.fetcher.getDataSource())        || helper.hasLoa@R_419_5819@(loadData.fetcher.getDat  aClass()))) {      started = true;      // 关注点6 通过loadData对象的fetcher对象(有关注点3的分析可知其实现类为httpUrlFetcher)的      // loadData方法来获取图片数据      loadData.fetcher.loadData(helper.getPriority(),     this);    }  }  return started;}复制代码

12、DecodeHelper#getLoadData

List<LoadData<?>> getLoadData() {    if (!isLoadDataSet) {      isLoadDataSet = true;      loadData.clear();      List<ModelLoader<Object, ?>> modelLoaders =   glIDeContext.getRegistry().getModelLoaders(model)  ;      //noinspection ForLoopReplaceableByForEach to   improve perf      for (int i = 0, size = modelLoaders.size(); i <   size; i++) {        ModelLoader<Object, ?> modelLoader =     modelLoaders.get(i);        // 注意:这里最终是通过httpGlIDeUrlLoader的buildLoadData获取到实际的loadData对象        LoadData<?> current =            modelLoader.buildLoadData(model, wIDth,     height, options);        if (current != null) {          loadData.add(current);        }      }    }    return loadData;}复制代码

13、httpGlIDeUrlLoader#buildLoadData

@OverrIDepublic LoadData<inputStream> buildLoadData(@NonNull   GlIDeUrl model, int wIDth, int height,    @NonNull Options options) {  // GlIDeUrls memoize parsed URLs so caching them     saves a few object instantiations and time  // spent parsing urls.  GlIDeUrl url = model;  if (modelCache != null) {    url = modelCache.get(model, 0, 0);    if (url == null) {      // 关注点5      modelCache.put(model, 0, 0, model);      url = model;    }  }  int timeout = options.get(TIMEOUT);  // 注意,这里创建了一个DataFetcher的实现类httpUrlFetcher  return new LoadData<>(url, new httpUrlFetcher(url,     timeout));}// 关注点5public voID put(A model, int wIDth, int height, B value) {    ModelKey<A> key = ModelKey.get(model, wIDth,     height);    // 最终是通过LruCache来缓存对应的值,key是一个ModelKey对象(由model、wIDth、height三个属性组成)    cache.put(key, value);}复制代码

从这里的分析,我们明白了httpUrlFetcher实际上就是最终的请求执行者,而且,我们知道了GlIDe会使用LruCache来对解析后的url来进行缓存,以便后续可以省去解析url的时间。

14、httpUrlFetcher#loadData

@OverrIDepublic voID loadData(@NonNull Priority priority,    @NonNull DataCallback<? super inputStream>   callback) {  long startTime = LogTime.getLogTime();  try {    // 关注点6    // loadDataWithRedirects内部是通过httpURLConnection网络请求数据    inputStream result =   loadDataWithRedirects(glIDeUrl.toURL(), 0, null,   glIDeUrl.getheaders());    // 请求成功回调onDataReady()    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));    }  }}private inputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,  Map<String, String> headers) throws IOException {        ...    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();    // 只要是2xx形式的状态码则判断为成功    if (ishttpOk(statusCode)) {      // 从urlConnection中获取资源流      return getStreamForSuccessfulRequest(urlConnection);    } else if (ishttpRedirect(statusCode)) {          ...            // 重定向请求      return loadDataWithRedirects(redirectUrl, redirects + 1, url,   headers);    } else if (statusCode == INVALID_STATUS_CODE) {      throw new httpException(statusCode);    } else {      throw new httpException(urlConnection.getResponseMessage(),   statusCode);    }}private inputStream getStreamForSuccessfulRequest(httpURLConnection urlConnection)  throws IOException {    if (TextUtils.isEmpty(urlConnection.getContentEnCoding())) {      int contentLength = urlConnection.getContentLength();      stream = ContentLengthinputStream.obtain(urlConnection.getinputStr  eam(), contentLength);    } else {      if (Log.isLoggable(TAG, Log.DEBUG)) {        Log.d(TAG, "Got non empty content enCoding: " +     urlConnection.getContentEnCoding());      }      stream = urlConnection.getinputStream();    }    return stream;}复制代码

在httpUrlFetcher#loadData方法的loadDataWithRedirects里面,GlIDe通过原生的httpURLConnection进行请求后,并调用getStreamForSuccessfulRequest()方法获取到了最终的图片流。

15、DecodeJob#run

在我们通过HtttpUrlFetcher的loadData()方法请求得到对应的流之后,我们还必须对流进行处理得到最终我们想要的资源。这里我们回到第10步DecodeJob#run方法的关注点3处,这行代码将会对流进行解码。

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) {      // 关注点8       // 编码和发布最终得到的Resource<Bitmap>对象      notifyEncodeAndRelease(resource, currentDataSource);    } else {      runGenerators();    }} private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,  DataSource dataSource) throws GlIDeException {    try {      if (data == null) {        return null;      }      long startTime = LogTime.getLogTime();      // 核心代码      // 进一步包装了解码方法      Resource<R> result = decodeFromFetcher(data, dataSource);      if (Log.isLoggable(TAG, Log.VERBOSE)) {        logWithTimeAndKey("Decoded result " + result, startTime);      }      return result;    } finally {      fetcher.cleanup();    }}@SuppressWarnings("unchecked")private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)  throws GlIDeException {    Loa@R_419_5819@<Data, ?, R> path = decodeHelper.getLoa@R_419_5819@((Class<Data>) data.getClass());    // 核心代码    // 将解码任务分发给Loa@R_419_5819@    return runLoa@R_419_5819@(data, dataSource, path);}private <Data, ResourceType> Resource<R> runLoa@R_419_5819@(Data data, DataSource dataSource,  Loa@R_419_5819@<Data, ResourceType, R> path) throws GlIDeException {    Options options = getoptionsWithHarDWareConfig(dataSource);    // 将数据进一步包装    DataRewinder<Data> rewinder =     glIDeContext.getRegistry().getRewinder(data);    try {      // ResourceType in DecodeCallback below is required for   compilation to work with gradle.      // 核心代码      // 将解码任务分发给Loa@R_419_5819@      return path.load(          rewinder, options, wIDth, height, new   DecodeCallback<ResourceType>(dataSource));    } finally {      rewinder.cleanup();    }}复制代码

16、Loa@R_419_5819@#load

public Resource<Transcode> load(DataRewinder<Data> rewinder, @NonNull Options options, int wIDth,  int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlIDeException {List<Throwable> throwables = Preconditions.checkNotNull(ListPool.acquire());try {  // 核心代码  return loaDWithExceptionList(rewinder, options, wIDth, height, decodeCallback, throwables);} finally {  ListPool.release(throwables);}复制代码

}

private Resource<Transcode> loaDWithExceptionList(DataRewinder<Data> rewinder,      @NonNull Options options,      int wIDth, int height, DecodePath.DecodeCallback<ResourceType>   decodeCallback,      List<Throwable> exceptions) throws GlIDeException {    Resource<Transcode> result = null;    //noinspection ForLoopReplaceableByForEach to improve perf    for (int i = 0, size = decodePaths.size(); i < size; i++) {      DecodePath<Data, ResourceType, Transcode> path =   decodePaths.get(i);      try {        // 核心代码        // 将解码任务又进一步分发给DecodePath的decode方法去解码        result = path.decode(rewinder, wIDth, height, options,     decodeCallback);      } catch (GlIDeException e) {        exceptions.add(e);      }      if (result != null) {        break;      }    }    if (result == null) {      throw new GlIDeException(failureMessage, new   ArrayList<>(exceptions));    }    return result;}复制代码

17、DecodePath#decode

public Resource<Transcode> decode(DataRewinder<DataType> rewinder,     int wIDth, int height,      @NonNull Options options, DecodeCallback<ResourceType> callback)   throws GlIDeException {    // 核心代码    // 继续调用DecodePath的decodeResource方法去解析出数据    Resource<ResourceType> decoded = decodeResource(rewinder, wIDth,     height, options);    Resource<ResourceType> transformed =     callback.onResourceDecoded(decoded);    return transcoder.transcode(transformed, options);}@NonNullprivate Resource<ResourceType> decodeResource(DataRewinder<DataType>   rewinder, int wIDth,    int height, @NonNull Options options) throws GlIDeException {  List<Throwable> exceptions =     Preconditions.checkNotNull(ListPool.acquire());  try {    // 核心代码    return decodeResourceWithList(rewinder, wIDth, height, options,   exceptions);  } finally {    ListPool.release(exceptions);  }}@NonNullprivate Resource<ResourceType>   decodeResourceWithList(DataRewinder<DataType> rewinder, int wIDth,    int height, @NonNull Options options, List<Throwable> exceptions)   throws GlIDeException {  Resource<ResourceType> result = null;  //noinspection ForLoopReplaceableByForEach to improve perf  for (int i = 0, size = decoders.size(); i < size; i++) {    ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);    try {      DataType data = rewinder.rewindAndGet();      if (decoder.handles(data, options)) {        // 获取包装的数据        data = rewinder.rewindAndGet();        // 核心代码         // 根据DataType和ResourceType的类型分发给不同的解码器Decoder        result = decoder.decode(data, wIDth, height, options);      }    } catch (IOException | RuntimeException | OutOfMemoryError e) {      if (Log.isLoggable(TAG, Log.VERBOSE)) {        Log.v(TAG, "Failed to decode data for " + decoder, e);      }      exceptions.add(e);    }    if (result != null) {      break;    }  }  if (result == null) {    throw new GlIDeException(failureMessage, new   ArrayList<>(exceptions));  }  return result;}复制代码

可以看到,经过一连串的嵌套调用,最终执行到了decoder.decode()这行代码,decode是一个ResourceDecoder<DataType, ResourceType>接口(资源解码器),根据不同的DataType和ResourceType它会有不同的实现类,这里的实现类是ByteBufferBitmapDecoder,接下来让我们来看看这个解码器内部的解码流程。

18、ByteBufferBitmapDecoder#decode

/** * Decodes {@link androID.graphics.Bitmap Bitmaps} from {@link    java.nio.ByteBuffer ByteBuffers}. */public class ByteBufferBitmapDecoder implements     ResourceDecoder<ByteBuffer, Bitmap> {    ...  @OverrIDe  public Resource<Bitmap> decode(@NonNull ByteBuffer source, int wIDth,   int height,      @NonNull Options options)      throws IOException {    inputStream is = ByteBufferUtil.toStream(source);    // 核心代码    return downsampler.decode(is, wIDth, height, options);  }}复制代码

可以看到,最终是使用了一个downsampler,它是一个压缩器,主要是对流进行解码,压缩,圆角等处理。

19、DownSampler#decode

public Resource<Bitmap> decode(inputStream is, int outWIDth, int outHeight,  Options options) throws IOException {    return decode(is, outWIDth, outHeight, options, EMPTY_CALLBACKS);} @SuppressWarnings({"resource", "deprecation"})public Resource<Bitmap> decode(inputStream is, int requesteDWIDth, int requestedHeight,      Options options, DecodeCallbacks callbacks) throws IOException {    Preconditions.checkArgument(is.markSupported(), "You must provIDe an     inputStream that supports"        + " mark()");    ...    try {      // 核心代码      Bitmap result = decodeFromWrappedStreams(is, bitmapFactoryOptions,          downsampleStrategy, decodeFormat, isHarDWareConfigAllowed,   requesteDWIDth,          requestedHeight, fixBitmapToRequestedDimensions, callbacks);      // 关注点7         // 解码得到Bitmap对象后,包装成BitmapResource对象返回,      // 通过内部的get方法得到Resource<Bitmap>对象      return BitmapResource.obtain(result, bitmapPool);    } finally {      releaSEOptions(bitmapFactoryOptions);      byteArrayPool.put(bytesForOptions);    }}private Bitmap decodeFromWrappedStreams(inputStream is,      BitmapFactory.Options options, DownsampleStrategy downsampleStrategy,      DecodeFormat decodeFormat, boolean isHarDWareConfigAllowed, int requesteDWIDth,      int requestedHeight, boolean fixBitmapToRequestedDimensions,      DecodeCallbacks callbacks) throws IOException {        // 省去计算压缩比例等一系列非核心逻辑    ...        // 核心代码    Bitmap downsampled = decodeStream(is, options, callbacks, bitmapPool);    callbacks.onDecodeComplete(bitmapPool, downsampled);    ...    // Bimtap旋转处理    ...        return rotated;}private static Bitmap decodeStream(inputStream is,     BitmapFactory.Options options,      DecodeCallbacks callbacks, BitmapPool bitmapPool) throws   IOException {        ...        transformationUtils.getBitmapDrawableLock().lock();    try {      // 核心代码      result = BitmapFactory.decodeStream(is, null, options);    } catch (IllegalArgumentException e) {      ...    } finally {      transformationUtils.getBitmapDrawableLock().unlock();    }    if (options.inJustDecodeBounds) {      is.reset();    }    return result;}复制代码

从以上源码流程我们知道,最后是在DownSampler的decodeStream()方法中使用了BitmapFactory.decodeStream()来得到Bitmap对象。然后,我们来分析下图片时如何显示的,我们回到步骤19的DownSampler#decode方法,看到关注点7,这里是将Bitmap包装成BitmapResource对象返回,通过内部的get方法可以得到Resource对象,再回到步骤15的DecodeJob#run方法,这是使用了notifyEncodeAndRelease()方法对Resource对象进行了发布。

20、DecodeJob#notifyEncodeAndRelease

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的源码可知,它实现了DecodeJob.CallBack这个接口。

class EngineJob<R> implements DecodeJob.Callback<R>,    Poolable {    ...}复制代码

21、EngineJob#onResourceReady

@OverrIDepublic voID onResourceReady(Resource<R> resource, DataSource   dataSource) {  this.resource = resource;  this.dataSource = dataSource;  MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();}private static class MainThreadCallback implements Handler.Callback{    ...    @OverrIDe    public boolean handleMessage(Message message) {      EngineJob<?> job = (EngineJob<?>) message.obj;      switch (message.what) {        case MSG_COMPLETE:          // 核心代码          job.handleResultOnMainThread();          break;        ...      }      return true;    }}复制代码

从以上源码可知,通过主线程Handler对象进行切换线程,然后在主线程调用了handleResultOnMainThread这个方法。

@SyntheticvoID handleResultOnMainThread() {  ...  //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.onResourceReady(engineResource, dataSource);    }  }   ...}复制代码

这里又通过一个循环调用了所有ResourceCallback的方法,让我们回到步骤9处Engine#load方法的关注点8这行代码,这里对ResourceCallback进行了注册,在步骤8出SingleRequest#onSizeReady方法里的engine.load中,我们看到最后一个参数,传入的是this,可以明白,engineJob.addCallback(cb)这里的cb的实现类就是SingleRequest。接下来,让我们看看SingleRequest的onResourceReady方法。

22、SingleRequest#onResourceReady

/** * A callback method that should never be invoked directly. */@SuppressWarnings("unchecked")@OverrIDepublic voID onResourceReady(Resource<?> resource, DataSource   dataSource) {  ...    // 从Resource<Bitmap>中得到Bitmap对象  Object received = resource.get();    ...    onResourceReady((Resource<R>) resource, (R) received, dataSource);}private voID onResourceReady(Resource<R> resource, R resultDataSource dataSource) {    ...    try {      ...      if (!anyListenerHandledUpdatingTarget) {        Transition<? super R> animation =            animationFactory.build(dataSource, isFirstResource);        // 核心代码        target.onResourceReady(result, animation);      }    } finally {      isCallingCallbacks = false;    }    notifyLoadSuccess();}复制代码

在SingleRequest#onResourceReady方法中又调用了target.onResourceReady(result, animation)方法,这里的target其实就是我们在into方法中建立的那个BitmAPImageVIEwTarget,看到BitmAPImageVIEwTarget类,我们并没有发现onResourceReady方法,但是我们从它的子类ImageVIEwTarget中发现了onResourceReady方法,从这里我们继续往下看。

23、ImageVIEwTarget#onResourceReady

public abstract class ImageVIEwTarget<Z> extends VIEwTarget<ImageVIEw, Z>implements Transition.VIEwAdapter {    ...    @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) {        // Order matters here. Set the resource first to make sure that the         Drawable has a valID and        // non-null Callback before starting it.        // 核心代码        setResource(resource);        maybeUpdateAnimatable(resource);    }        // 核心代码    protected abstract voID setResource(@Nullable Z resource);}复制代码

这里我们在回到BitmAPImageVIEwTarget的setResource方法中,我们终于看到Bitmap被设置到了当前的imageVIEw上了。

public class BitmAPImageVIEwTarget extends ImageVIEwTarget<Bitmap> {    ...            @OverrIDe    protected voID setResource(Bitmap resource) {      vIEw.setimageBitmap(resource);    }}复制代码

到这里,我们的分析就结束了,从以上的分析可知,GlIDe将大部分的逻辑处理都放在了最后一个into方法中,里面经过了20多个分析步骤才将请求图片流、解码出图片,到最终设置到对应的imageVIEw上。

最后,这里给出一份我花费了数个小时绘制的完整GlIDe加载流程图,非常珍贵,大家可以仔仔细细再把GlIDe的主体流程在梳理一遍。

五、总结

到此,GlIDe整个的加载流程分析就结束了,可以看到,GlIDe最核心的逻辑都聚集在into()方法中,它里面的设计精巧而复杂,这部分的源码分析非常耗时,但是,如果你真真正正地去一步步去深入其中,你也许在AndroID进阶之路上将会有顿悟的感觉。


链接:https://juejin.cn/post/6844904049595121672

总结

以上是内存溢出为你收集整理的Android主流三方库源码分析(三、深入理解Glide源码)全部内容,希望文章能够帮你解决Android主流三方库源码分析(三、深入理解Glide源码)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1038312.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存