美文网首页
Glide源码流程分析

Glide源码流程分析

作者: 涂文涛 | 来源:发表于2020-04-19 14:53 被阅读0次


Glide.with(this).load("").into();

with()方法:包含Glide的初始化, 以及RequestManager的初始化

Glide内:RequestManager的初始化

@NonNull

public static RequestManager with(@NonNull FragmentActivity activity) {

   return getRetriever(activity).get(activity);

}

@NonNull

   public RequestManager get(@NonNull FragmentActivity activity) {

       if (Util.isOnBackgroundThread()) {

           return this.get(activity.getApplicationContext());

       } else {

           assertNotDestroyed(activity);

           androidx.fragment.app.FragmentManager fm = activity.getSupportFragmentManager();

           return this.supportFragmentGet(activity, fm, (Fragment)null, isActivityVisible(activity));

       }

   }

    @NonNull

   private RequestManager supportFragmentGet(@NonNull Context context, @NonNull androidx.fragment.app.FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {

       SupportRequestManagerFragment current = this.getSupportRequestManagerFragment(fm, parentHint, isParentVisible);//1.生成一个fragment

       RequestManager requestManager = current.getRequestManager();

       if (requestManager == null) {

           Glide glide = Glide.get(context);

           requestManager = this.factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);//2.使用工厂RequestManagerFactory生成一个RequestManager

           current.setRequestManager(requestManager);//3.将requestManager与生成的SupportRequestManagerFragment进行绑定

       }

       return requestManager;

   }

以Activity为例子:

1.首先会为当前activity生成绑定一个SupportRequestManagerFragment

2.使用工厂RequestManagerFactory生成一个RequestManager,参数分别是Gilde,LifeCycle, SupportFragmentRequestManagerTreeNode(),上下文本身(这里指的activity)

3.将requestManager与生成的SupportRequestManagerFragment进行绑定

laod()方法:-> 返回一个RequestBuilder<Drawable>

RequestManager内:

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);//1.生成一个RequestBilder 参数分别是gilde ResuestManager,Drawable.class,context上下文(activity)

}

RequestBuilder内:

@Override

  public RequestBuilder<TranscodeType> load(@Nullable Object model) {

   return loadGeneric(model);

  }

  @NonNull

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

   this.model = model;

   isModelSet = true;

   return this;

  }

这里以load(参数为string资源连接)为例:

1.生成一个RequestBilder 参数分别是gilde ResuestManager,Drawable.class,context上下文(activity)

2.将传入的资源链接(图片链接"xxx")赋值给内部私有变量private Object model 并返回RequestBilder

into()方法:

RequestBilder内:into参数以ImageView为例

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

  Util.assertMainThread();//UI操作必须是在UI线程进行

  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()) { //根据设置的scaleType初始化不同的Options

     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.

   }

  }

  return into(

     glideContext.buildImageViewTarget(view, transcodeClass), //返回一个DrawableImageViewTarget

     /*targetListener=*/ null,

     requestOptions);

}

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

     @NonNull Y target, // 类型为DrawableImageViewTarget

     @Nullable RequestListener<TranscodeType> targetListener,

     @NonNull RequestOptions options) {

   Util.assertMainThread();

   Preconditions.checkNotNull(target);

   if (!isModelSet) {

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

   }

   options = options.autoClone();

   //参数 target==DrawableImageViewTarget, targetListener == null

   Request request = buildRequest(target, targetListener, options); //1.构建并返回一个SingleRequest

   Request previous = target.getRequest();

   if (request.isEquivalentTo(previous)

       && !isSkipMemoryCacheWithCompletePreviousRequest(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).isRunning()) {

       // 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.给目标imageView设置tag标记

   requestManager.track(target, request); //3.运行Request 开始从三级缓存以及网络中请求数据

   return target;

  }

into方法内部三步:

1.构建并返回一个SingleRequest

2.给目标imageView设置tag标记

3.运行Request 开始从三级缓存以及网络中请求数据

真正开始请求数据的地方:3. requestManager.track(target, request)  参数为返回一个DrawableImageViewTarget以及SingleRequest

RequestManager内部:

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

  targetTracker.track(target);

  requestTracker.runRequest(request); //执行request

}

RequestTracker内:

public void runRequest(@NonNull Request request) {

  requests.add(request);

  if (!isPaused) {

   request.begin(); //SingleRequest begin()

  } else {

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

     Log.v(TAG, "Paused, delaying request");

   }

   pendingRequests.add(request);

  }

}

SingleRequest内:

@Override

public void begin() {

  assertNotCallingCallbacks();

  stateVerifier.throwIfRecycled();

  startTime = LogTime.getLogTime();

  if (model == null) {

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

     width = overrideWidth;

     height = overrideHeight;

   }

   // Only log at more verbose log levels if the user has set a fallback drawable, because

   // fallback Drawables indicate the user expects null models occasionally.

   int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;

   onLoadFailed(new GlideException("Received null model"), logLevel);

   return;

  }

  if (status == Status.RUNNING) {

   throw new IllegalArgumentException("Cannot restart a running request");

  }

  // If we're restarted after we're complete (usually via something like a notifyDataSetChanged

  // that starts an identical request into the same Target or View), we can simply use the

  // resource and size we retrieved the last time around and skip obtaining a new size, starting a

  // new load etc. This does mean that users who want to restart a load because they expect that

  // the view size has changed will need to explicitly clear the View or Target before starting

  // the new load.

  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)) { //判断ImageView宽高是否正确

   onSizeReady(overrideWidth, overrideHeight); //开始加载

  } else {

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

  }

}

@Override

  public 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; //修改加载的状态为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));

   }

   //真正开始加载数据到来

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

public <R> LoadStatus load(

   GlideContext glideContext,

   Object model,

   Key signature,

   int width,

   int height,

   Class<?> resourceClass,

   Class<R> transcodeClass,

   Priority priority,

   DiskCacheStrategy diskCacheStrategy,

   Map<Class<?>, Transformation<?>> transformations,

   boolean isTransformationRequired,

   boolean isScaleOnlyOrNoTransform,

   Options options,

   boolean isMemoryCacheable,

   boolean useUnlimitedSourceExecutorPool,

   boolean useAnimationPool,

   boolean onlyRetrieveFromCache,

   ResourceCallback cb) {

  Util.assertMainThread();

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

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

     resourceClass, transcodeClass, options);

    //1.首先从正在活动的视图资源ActiveResources中开始取

  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;

  }

    //2.从LruCache内存缓存中取

  EngineResource<?> cached = loadFromCache(key, isMemoryCacheable); //

  if (cached != null) {

   cb.onResourceReady(cached, DataSource.MEMORY_CACHE);

   if (VERBOSE_IS_LOGGABLE) {

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

   }

   return null;

  }

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

  if (current != null) {

   current.addCallback(cb);

   if (VERBOSE_IS_LOGGABLE) {

     logWithTimeAndKey("Added to existing load", startTime, key);

   }

   return new LoadStatus(cb, current);

  }

  EngineJob<R> engineJob =

     engineJobFactory.build(

         key,

         isMemoryCacheable,

         useUnlimitedSourceExecutorPool,

         useAnimationPool,

         onlyRetrieveFromCache);

  DecodeJob<R> decodeJob =

     decodeJobFactory.build(

         glideContext,

         model,

         key,

         signature,

         width,

         height,

         resourceClass,

         transcodeClass,

         priority,

         diskCacheStrategy,

         transformations,

         isTransformationRequired,

         isScaleOnlyOrNoTransform,

         onlyRetrieveFromCache,

         options,

         engineJob);

  jobs.put(key, engineJob);

  engineJob.addCallback(cb);

  engineJob.start(decodeJob); //3.从硬盘缓存中取

  if (VERBOSE_IS_LOGGABLE) {

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

  }

  return new LoadStatus(cb, engineJob);

}

1.首先从正在活动的视图资源ActiveResources中开始取

2.从LruCache内存缓存中取

3.从硬盘缓存中取

相关文章

网友评论

      本文标题:Glide源码流程分析

      本文链接:https://www.haomeiwen.com/subject/qlxmbhtx.html