Android框架源码分析——Glide源码分析

1、Glide的使用

    Glide.with(this).load(url).into(imageView)

在当下Glide已经是很常见的图片加载工具了,相信很多开发者都体会到其方便指出,Glide的使用就简单一句话即可完成图片的加载,但不要小看这句话,Glide的背后可是作出了成吨的工作,今天整理一下Glide的相关笔记,跟随上面的一句代码探索Glide的奇妙指出;

2、with()

   public static RequestManager with(@NonNull FragmentActivity activity) {
      return getRetriever(activity).get(activity);
    }
  • getRetriever(activity):获取RequestManagerRetriever
       private static RequestManagerRetriever getRetriever(@Nullable Context context) {
          return Glide.get(context).getRequestManagerRetriever(); 
        }

从上面的代码看出with()中直接调用一行代码,这行代码执行了getRetriever()和get()两个方法,getRetriever()中获取Glide的实例,然后获取Glide配置中的RequestManagerRetriever对象,下面先看看Glide的初始化

2.1、Glide初始化
   private static void initializeGlide(@NonNull Context context) {
      initializeGlide(context, new GlideBuilder());
    }
    @SuppressWarnings("deprecation")
    private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
      //(1)获取@GlideModules注解生成的类
      GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
       //(2)调用扩展GlideModule中的设置方法,加载初始化的配置,这里可以在项目中自定义Glide的配置
      annotationGeneratedModule.applyOptions(applicationContext, builder); 
      Glide glide = builder.build(applicationContext); //(3)执行build()实例化Glide
      Glide.glide = glide; //(4)赋值单例提供的Glide
    }

简述上面的流程:

  1. 创建GlideBuilder实例,然后反射获取程序中扩展的@GlideModule生成类,调用applyOptions()加载用户自定义的配置,这里的针对Glide的Generated API使用时的配置,关于Generated API的使用自行查阅文档
  2. 使用GlideBuilder实例化Glide,并单例对外提供
2.2、GlideBuilder——配置并实例化Glide
Glide build(@NonNull Context context) {
  if (sourceExecutor == null) {
    sourceExecutor = GlideExecutor.newSourceExecutor(); //(1)实例化执行网络资源加载线程池
  }
  if (diskCacheExecutor == null) {
    diskCacheExecutor = GlideExecutor.newDiskCacheExecutor(); //(2)实例化执行磁盘缓存的线程池
  }
  if (animationExecutor == null) {
    animationExecutor = GlideExecutor.newAnimationExecutor(); //(3)实例化动画线程池
  }
  if (memorySizeCalculator == null) {
    memorySizeCalculator = new MemorySizeCalculator.Builder(context).build(); //(4)实例化计算内存缓存大小
  }
  if (connectivityMonitorFactory == null) {
    connectivityMonitorFactory = new DefaultConnectivityMonitorFactory(); //(5)
  }
  if (bitmapPool == null) {
    int size = memorySizeCalculator.getBitmapPoolSize();
    if (size > 0) {
      bitmapPool = new LruBitmapPool(size); //(6)初始化Bitmap池
    } else {
      bitmapPool = new BitmapPoolAdapter();
    }
  }
  if (arrayPool == null) {
    arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes()); //(7)
  }
  if (memoryCache == null) {
    memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());//(8)初始化内存缓存
  }
  if (diskCacheFactory == null) {
    diskCacheFactory = new InternalCacheDiskCacheFactory(context); //(9)实例化磁盘缓存工厂
  }
  if (engine == null) { //(10)将设置的信息初始化Engine
    engine = new Engine(
            memoryCache,
            diskCacheFactory,
            diskCacheExecutor,
            sourceExecutor,
            GlideExecutor.newUnlimitedSourceExecutor(),
            animationExecutor,
            isActiveResourceRetentionAllowed);
  }
   defaultRequestListeners = Collections.emptyList(); //(11)请求监听器
  
  RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(requestManagerFactory);12return new Glide( //(13)创建Glide
      context,
      engine,
      memoryCache,
      bitmapPool,
      arrayPool,
      requestManagerRetriever,
      connectivityMonitorFactory,
      logLevel,
      defaultRequestOptions.lock(),
      defaultTransitionOptions,
      defaultRequestListeners,
      isLoggingRequestOriginsEnabled);
}

GlideBuilder初始化Gild时,完成了各种线程池和缓存的创建和配置,具体见代码中的注释这里很多的配置对后面的分析很重要,最后创建的RequestManagerRetriever就是上面获取的实例

  • RequestManagerRetriever.get():根据传入的Context不同分别调用不同的重载方法创建RequestManager
public RequestManager get(@NonNull Fragment fragment) {//get()多个重载方法
  if (Util.isOnBackgroundThread()) { //(1)在后台线程执行时,绑定Application生命周期
    return get(activity.getApplicationContext()); 
  } else {
    FragmentManager fm = activity.getSupportFragmentManager(); //
    return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
  }
}
public RequestManager get(@NonNull Activity activity) { //get()对Activity的重载
if (Util.isOnBackgroundThread()) {
。。。。。。
return fragmentGet( activity, fm,null, isActivityVisible(activity));
}
}
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {  //get()对Fragment的重载
  if (Util.isOnBackgroundThread()) { 
。。。。。。
    return supportFragmentGet(  activity, fm,null, isActivityVisible(activity));
  }
}
public RequestManager get(@NonNull Context context) { //get()对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); //对于传入Application Context的调用getApplicationManager()绑定Application周期
}
@NonNull
private RequestManager getApplicationManager(@NonNull Context context) {
  if (applicationManager == null) {
    synchronized (this) {
      if (applicationManager == null) {
        Glide glide = Glide.get(context.getApplicationContext());
        applicationManager =
            factory.build(
                glide,
                new ApplicationLifecycle(),
                new EmptyRequestManagerTreeNode(),
                context.getApplicationContext());
      }
    }
  }
  return applicationManager;
}
//对于非Application,根据传入的Activity/Fragment的包(app或v4)分别调用fragmentGet或supportFragmentGet,最终目的都在Activity/Fragment中添加隐藏的Fragment
@NonNull
private RequestManager supportFragmentGet(
    @NonNull Context context,
    @NonNull FragmentManager fm,
    @Nullable Fragment parentHint,
    boolean isParentVisible) {
  //(1)从传入的fm中获取添加的Fragment,如果为null则创建并使用fm添加一个隐藏的Fragment,用于监听生命周期的变化
  SupportRequestManagerFragment current =     
      getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
  RequestManager requestManager = current.getRequestManager();
  if (requestManager == null) {
    Glide glide = Glide.get(context); 
 //(2)调用factory创建RequestManager,传入ActivityFragmentLifecycle()监听Fragment的生命周期,然后绑定RequestManager和Fragment
    requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
    current.setRequestManager(requestManager); 
  }
  return requestManager;
}

总结:

  1. get()方法中主要是根据请求传入的Context类型,执行不同逻辑用于确定请求的生命周期,这里采用常见的添加隐形Fragment的方式监听生命周期
  2. 传入Application类型的Context调用get()绑定Application生命周期
  3. 传入Activity/Fragment类型Context,若在非UI线程,则绑定Application周期,在UI线程为Activity/Fragment添加隐形Fragment监听生命周期
  4. 绑定生命周期实例化Glide后,调用factory创建RequestManager实例,这里默认使用RequestManagerFactory
  5. RequestManagerFactory:Glide的默认工厂,实例化RequestManager保存请求的生命周期lifecycle,关于lifecycle如何控制生命周期在后面将会介绍;
requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//(1)factory默认的是RequestManagerFactory
private 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);//(2)创建RequestManager
  }
};

3、load()

public RequestBuilder<Drawable> load(@Nullable String string) {
  return asDrawable().load(string); 
}
public RequestBuilder<Drawable> asDrawable() {
  return as(Drawable.class); 
}
public <ResourceType> RequestBuilder<ResourceType> as( @NonNull Class<ResourceType> resourceClass) {
  return new RequestBuilder<>(glide, this, resourceClass, context); //创建RequestBuilder
}
  • RequestBuilder.load():保存请求的数据(图片地址)
public RequestBuilder<TranscodeType> load(@Nullable String string) {
  return loadGeneric(string);
}
@NonNull
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
  this.model = model; //保存请求的url
  return this;
}

在with()中知道程序最终创建了RequestManager对象,RequestManager.load()方法中根据传参类型创建对应的RequestBuilder并设置加载最终返回的数据类型,然后调用RequestBuilder.load(),此处传入的数据类型将影响最终加载图片的类型,因为在加载完成后会根据此处设置的resourceClass进行响应的转换;

4、into():加载图片显示到视图中

public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
switch (view.getScaleType()) { // (1)根据ImageView的scaleType设置RequestOptions
  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;
}
  return into( // (2)执行into()
      glideContext.buildImageViewTarget(view, transcodeClass),
      null,
      requestOptions,
      Executors.mainThreadExecutor());
}

into()方法中代码逻很简洁:

  • 根据设置ImageView条件配置响应的Options;

  • 根据要加载的图片类型,创建对应Target,此处的Target保存真正的ImageView并负责最终的图片显示

  • 设置请求后的显示线程为主线程

  • 调用into()执行图片加载

  • GlideContext.buildImageViewTarget():根据请求的数据类型,调用ImageViewTargetFactory创建对应的Target,创建的Target封装试图View,这里以请求的Drawable为例,此处创建的是DrawableImageViewTarget

@NonNull
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
    @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
  return imageViewTargetFactory.buildTarget(imageView, transcodeClass);   //此处的transcodeClass由上面知道传递的是Drawable.class
}
public class ImageViewTargetFactory {
  @NonNull
  @SuppressWarnings("unchecked")
  public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
      @NonNull Class<Z> clazz) {
    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); //创建DrawableImageViewTarget
    } else { 
  }
}
  • into():构建最终的请求Request并执行请求
private <Y extends Target<TranscodeType>> Y into(
    @NonNull Y target,
    @Nullable RequestListener<TranscodeType> targetListener,
    BaseRequestOptions<?> options,
    Executor callbackExecutor) {
  Request request = buildRequest(target, targetListener, options, callbackExecutor); //(1)构建Request
  target.setRequest(request); //(2)调用ViewTarget保存Request
  requestManager.track(target, request); //(3)执行Request请求
  return target;
}

上面的代码就做了两件事,但这两件事完成了整个的数据请求:

  1. 创建Request,此处最终创建的是SingleRequest
  2. 执行Request加载
4.1、创建SingleRequest实例
public static <R> SingleRequest<R> obtain(……){
  SingleRequest<R> request = (SingleRequest<R>) POOL.acquire();  //(1)获取或创建Request
  if (request == null) {
      request = new SingleRequest<>(); //创建Request
  }
  request.init( //调用Request.init()初始化请求信息和图片加载信息
    context, 
    glideContext,
    model,  //请求的地址
    transcodeClass, //请求参数类型,此处为String
    requestOptions, //设置的options
    overrideWidth, //设置的宽、高参数
    overrideHeight,
    priority,
    target,  //设置显示的Target
    targetListener,  //设置监听Target的加载
    requestListeners,   //设置请求监听
    requestCoordinator,
    engine, 
    animationFactory, //加载动画
    callbackExecutor); //设置执行的线程池
 }
4.2、执行Request,开始加载数据
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
  requestTracker.runRequest(request); //执行请求的Target
}
  • RequestTracker.runRequest():方法最终调用SingleRequest的方法
public void runRequest(@NonNull Request request) {
  requests.add(request);   //保存请求的Request
  if (!isPaused) { //判断Glide是否暂停
    request.begin(); //直接进行请求
  } else {
    request.clear();
    pendingRequests.add(request); //暂停时保存任务
  }
}

runRequest中首先保存要执行的请求,然后判断Glide的加载是否停止,初步猜测这里的停止应该和生命周期有关,如果停止将请求Request加入到人去列表中,否则直接调用begin()执行Request

  • SingleRequest.begin()
@Override
public synchronized void begin() {
  status = Status.WAITING_FOR_SIZE; //设置标识位为测量尺寸
  if (Util.isValidDimensions(overrideWidth, overrideHeight)) {  //如果已设置宽高尺寸,则直接调用 onSizeReady(),否则测量尺寸后再调用
    onSizeReady(overrideWidth, overrideHeight);
  } else {
    target.getSize(this); //测量后调用
  }
  if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
      && canNotifyStatusChanged()) {
    target.onLoadStarted(getPlaceholderDrawable()); //回调请求开始,显示占位Drawable
  }
}

begin()方法执行3个过程:

  1. 如果已设置宽高尺寸,则直接调用 onSizeReady()
  2. 如果未设置则调用ImageView的测量方法,测量结束后回调onSizeReady()
  3. 回调target.onLoadStarted(getPlaceholderDrawable())表示加载开始显示占位图
  • SingleRequest.onSizeReady():继续请求加载
public synchronized void onSizeReady(int width, int height) {
  status = Status.RUNNING;
  loadStatus = engine.load( 
          glideContext,
          model, //请求参数
          requestOptions.getSignature(), //请求的requestOptions
          this.width, //请求宽、高
          this.height,
          requestOptions.getResourceClass(),
          transcodeClass, //请求参数类型
          priority,
          requestOptions.getDiskCacheStrategy(), //请求设置的RequestOptions
          requestOptions.getTransformations(),
          requestOptions.isTransformationRequired(),
          requestOptions.isScaleOnlyOrNoTransform(),
          requestOptions.getOptions(),
          requestOptions.isMemoryCacheable(),
          requestOptions.getUseUnlimitedSourceGeneratorsPool(),
          requestOptions.getUseAnimationPool(),
          requestOptions.getOnlyRetrieveFromCache(),
          this, // 此处传递的是ResourceCallback,SingleRequest实现了ResourceCallback接口
          callbackExecutor); //执行线程池
}

onSizeReady中标记运行状态,调用Engine.load()加载数据,传入的参数也都是加载图片基本配置和条件;

  • Engine.load():执行加载数据
public synchronized <R> LoadStatus load() {
  EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations, //(1)创建缓存的Key
      resourceClass, transcodeClass, options);
  EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable); //(2)从活跃的引用中加载缓存信息
  
  EngineResource<?> cached = loadFromCache(key, isMemoryCacheable); //(3)从缓存中获取缓存实例
  EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache); //从缓存的Jobs列表中获取EngineJob
  if (current != null) {
    current.addCallback(cb, callbackExecutor);
    return new LoadStatus(cb, current);
  }
  EngineJob<R> engineJob =  engineJobFactory.build( //对于新执行的任务,创建EngineJob
          key,
          isMemoryCacheable,
          useUnlimitedSourceExecutorPool,
          useAnimationPool,
          onlyRetrieveFromCache);
  DecodeJob<R> decodeJob =  decodeJobFactory.build( //创建执行解析任务的DecodeJob
          glideContext,
          model,
          key,
          signature,
          width,
          height,
          resourceClass,
          transcodeClass,
          priority,
          diskCacheStrategy,
          transformations,
          isTransformationRequired,
          isScaleOnlyOrNoTransform,
          onlyRetrieveFromCache,
          options,
          engineJob); //在DecodeJob中添加DecodeJob.Callback实例,处理数据回调
  jobs.put(key, engineJob); //保存执行的任务信息
  engineJob.addCallback(cb, callbackExecutor); //将传入的SingleRequest和执行的线程池对应添加到列表中
  engineJob.start(decodeJob);  //启动执行任务
  return new LoadStatus(cb, engineJob);
}

load()中执行的逻辑就明显体现了Glide的缓存原理,详细的执行会在缓存中介绍,这里制作流程介绍,简单总结:

  1. 首先根据加载的条件创建Glide 的缓存Key;
  2. 根据Key先从活跃的资源中获取,获取成功则返回,否则向下执行;
  3. 再从内存缓存中获取,获取成功则返回,否则向下执行;
  4. 对于都未获取到的则创建DecodeJob和EngineJob加载并解析资源;
  • EngineJob.start():获取执行任务的线程池并执行任务
public synchronized void start(DecodeJob<R> decodeJob) {
  this.decodeJob = decodeJob;
  GlideExecutor executor = decodeJob.willDecodeFromCache()  //获取执行的线程池
      ? diskCacheExecutor
      : getActiveSourceExecutor();
  executor.execute(decodeJob); //使用线程池执行任务,程序回到DecodeJob.run()
}
  • DecodeJob.run():线程池执行加载的方法
@Override
public void run() {
    runWrapped();
}
private void runWrapped() {
  switch (runReason) {
    case INITIALIZE:
      stage = getNextStage(Stage.INITIALIZE);  //根据缓存情况获取下一步的执行条件
      currentGenerator = getNextGenerator();  //获取具体执行的DataFetcherGenerator实例
      runGenerators(); //执行Generators
      break;
    case SWITCH_TO_SOURCE_SERVICE:
      runGenerators();
      break;
    case DECODE_DATA:
      decodeFromRetrievedData();
      break;
  }
}

private Stage getNextStage(Stage current) {
  switch (current) {
    case INITIALIZE:
      return diskCacheStrategy.decodeCachedResource()  //(1)判断存在转换后缓存文件则返回Stage标识,否则递归继续判断
          ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
    case RESOURCE_CACHE:
      return diskCacheStrategy.decodeCachedData() //(2)判断存在源数据缓存存在,则设置Stage标识,否则递归继续判断
          ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
    case DATA_CACHE: //(3)解析后文件和源文件缓存都不存在的情况:
      return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE; //如果设置只读缓存则请求结束,否则获取资源
  }
}
//根据上一步设置的要执行的Stage的标识,获取执行的DataFetcherGenerator实例
private DataFetcherGenerator getNextGenerator() {
  switch (stage) {
    case RESOURCE_CACHE:
      return new ResourceCacheGenerator(decodeHelper, this);  //(1)从转换资源缓存中获取
    case DATA_CACHE:
      return new DataCacheGenerator(decodeHelper, this);  //(2)从缓存的源文件中获取
    case SOURCE:
      return new SourceGenerator(decodeHelper, this); //(3)没有缓存资源,执行加载
  }
}
//Glide巧妙的设置一次执行:获取处理缓存资源 -> 获取原始缓存资源 -> 网络加载;只要一个环节加载成功,返回true则跳出循环
private void runGenerators() {
  boolean isStarted = false;
  while (!isCancelled && currentGenerator != null
      && !(isStarted = currentGenerator.startNext())) { //调用startNext()执行加载,成功返回true,跳出循环
    stage = getNextStage(stage);
    currentGenerator = getNextGenerator();
  }
}

关于上面的代码还是需要仔细思考下的,Glide使用getNextStage()和getNextGenerator()方法巧妙的实现了多种判断,总结上面方法执行逻辑如下:

  1. getNextStage():根据当前状态获取下一步的操作类型,开始为INITIALIZE状态,此时判断是否有转换后的缓存,有则设置为RESOURCE_CACHE,否则继续回调判断;此时传入为RESOURCE_CACHE状态,判断是否有原数据缓存,有设置DATA_CACHE,否则递归判断,传参为DATA_CACHE;此时判断是否设置制度缓存,如果设置但没有缓存加载结束,未设置则设置SOURCE标识,表示要去加载资源;
  2. getNextGenerator():根据上一步设置的标识,创建对应的任务实例(读取转换后文件、源缓存文件、获取网络资源)
  3. runGenerators():执行任务,在执行结束后并设置标识
4.3、SourceGenerator
SourceGenerator(DecodeHelper<?> helper, FetcherReadyCallback cb) {
  this.helper = helper;
  this.cb = cb; //保存传入的FetcherReadyCallback实例
}
@Override
public boolean startNext() {
  while (!started && hasNextModelLoader()) {
      loadData = helper.getLoadData().get(loadDataListIndex++);  // loadData是在Glide初始化时注册的
      loadData.fetcher.loadData(helper.getPriority(), this); //获取Fetcher,真正执行网络请求的点地方,
    }
  }
  return started;
}

方法执行runGenerators()会调用SourceGenerator.statNext()方法,statNext首先使用helper获取loadData,此处的 helper是DecodeHelper实例,创建SourceGenerator时传入的参数,方法回到DecodeJob中,在DecodeJobFactory创建DecodeJob时掉调用了DecodeJob.init(),init()方法中decodeHelper.init初始化decodeHelper

private final DecodeHelper<R> decodeHelper = new DecodeHelper<>();
DecodeJob<R> init(
   ……….) {
  decodeHelper.init(
      glideContext,  
      diskCacheProvider); 
}

helper.getLoadData()获取ModelLoader.LoadData()对象,Glide初始化时调用.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())注册的HttpGlideUrlLoader.Factory(),最终创建new LoadData<>(url, new HttpUrlFetcher(url, timeout)),后面加载的loadData.fetcher 其实调用的就是HttpUrlFetcher实例;

  • HttpUrlFetcher :最终执行网络请求,使用HttpUrlConnection执行图片加载
@Override
public void loadData(@NonNull Priority priority,@NonNull DataCallback<? super InputStream> callback) {
    InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
}
//使用HttpUrl执行网络请求
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
    Map<String, String> headers) throws IOException {
  urlConnection = connectionFactory.build(url); //使用HttpUrlConnection执行网络请求
  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);
  urlConnection.setInstanceFollowRedirects(false);
  urlConnection.connect();
  stream = urlConnection.getInputStream();
  if (isCancelled) {
    return null;
  }

上面的逻辑很简介直接请求网络加载图片,Glide的默认使用HttpUrl加载图片,当然Glide也提供了配置Okhttp的方法;

5、请求成功回调

  • HttpUrlFetcher执行网络请求成功后,请求后回调的Callback,此处Callback是传入的SourceGenerator
 InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
    callback.onDataReady(result);   //执行请求成功回调
  } catch (IOException e) {
    callback.onLoadFailed(e);   //执行请求失败回调
  } finally {
  }
  • SourceGenerator.onDataReady()
@Override
public void onDataReady(Object data) {
  DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
  if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) { //判断是否缓存原始数据
    dataToCache = data;
    cb.reschedule();  // 缓存原始数据
  } else { //处理获取的数据
    cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,  // 此处的cb创建时传入的DecodeJob中创建的
        loadData.fetcher.getDataSource(), originalKey);
  }
}

如果Glide设置允许缓存源数据则执行数据缓存,否则执行DecodeJob.onDataFetcherReady进行转换资源,此处cb其实是传入的DecodeJob对象,所以方法回到进入DecodeJob;

  • DecodeJob.onDataFetcherReady():执行数据转换和解析
@Override
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,DataSource dataSource, Key attemptedKey) {
      decodeFromRetrievedData();
}
private void decodeFromRetrievedData() {
  Resource<R> resource = null;
  try {  //(1)执行图片的转换
    resource = decodeFromData(currentFetcher, currentData, currentDataSource);
  } catch (GlideException e) {
  }
  if (resource != null) {
    notifyEncodeAndRelease(resource, currentDataSource); //(2) 通知加载结束并缓存数据
  } else {
    runGenerators();
  }
}
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
  Resource<R> result = resource;
  notifyComplete(result, dataSource); // notifyCOmplete()调用callback.onResourceReady(resource, dataSource);
  stage = Stage.ENCODE;
}

总结:

  1. 调用decodeFromData执行图片的转换
  2. 通知加载结束并缓存数据,此处回到callback为EngineJob对象
  • EngineJob.onResourceReady():执行加载资源回调
class EngineJob<R> implements DecodeJob.Callback<R>{
@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
  synchronized (this) {
    this.resource = resource;
    this.dataSource = dataSource;
  }
  notifyCallbacksOfResult();
}
@Synthetic
void notifyCallbacksOfResult() {
  synchronized (this) {
}
for (final ResourceCallbackAndExecutor entry : copy) {
  entry.executor.execute(new CallResourceReady(entry.cb));  //调用线程池执行CallResourceReady
}
}

对上面最后执行代码中的entey其实是ResourceCallbacksAndExecutors()的实例,内部封装了List用于保存ResourceCallbackAndExecutor,代码中使用for循环遍历copy中的集合,那是什么时候添加的呢?这里代码回到Engine.load()中有一行代码(见下面),此时将cb保存到ResourceCallbackAndExecutor中,然而此处的cb就是SingleRequest中调用load()传入的this,即cb就是SingleRequest

engineJob.addCallback(cb, callbackExecutor);
  • CallResourceReady:对资源引用计数加一,回到将callCallbackOnResourceReady()将结果回传给SingleRequest
 @Override
  public void run() {
        engineResource.acquire();  
        callCallbackOnResourceReady(cb);  //加载结束回调方法
  }
}
synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
  try {
    cb.onResourceReady(engineResource, dataSource); 
  } 
}
  • SingleRequest.onResourceReady()
public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
  stateVerifier.throwIfRecycled();
  loadStatus = null;
  if (resource == null) {
    onLoadFailed(exception); //加载失败回调
    return;
  }
  Object received = resource.get();
  if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
    onLoadFailed(exception);
    return;
  }
  onResourceReady((Resource<R>) resource, (R) received, dataSource);    //执行成功数据回调
}
private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
  try {
    if (!anyListenerHandledUpdatingTarget) {
      target.onResourceReady(result, animation); //执行Target,此处就是前面创建的DrawableImageViewTarget
    }
  } finally {
    isCallingCallbacks = false;
  }
}

看到最初创建请求的地方代表离成功不远了,SingleRequest中根据加载的结果,回调Target中的方法,由前面的分析知道此时的Target是DrawableImageViewTarget实例

  • DrawableImageViewTarget
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
  if (transition == null || !transition.transition(resource, this)) {
    setResourceInternal(resource); //不执行显示动画
  } else {
    maybeUpdateAnimatable(resource); //执行显示动画
  }
}
private void setResourceInternal(@Nullable Z resource) {
  setResource(resource); //调用抽象方法,此方法在DrawableImageViewTarget中实现
  maybeUpdateAnimatable(resource);
}
@Override
protected void setResource(@Nullable Drawable resource) {
  view.setImageDrawable(resource);  //最终的显示结果
}
  1. ImageViewTarget.onResourceReady()中根据设置的transtion确定是否执行动画并分别处理
  2. 调用重写的抽象方法,为保存的ImageView设置图片

Glide的源码分析到此结束了,由于笔记很早之前就做了但一直没整理成博客,这次的整理又整体看了遍源码,即是复习也是学习,希望对想要了解的同学有所帮助;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章