Glide源码解析1:with()、load()、into()

Glide基本用法

Glide.with(context).load(obj).into(imageView)


with()源码解析

  • with方法根据传入参数不同有以下几种重载方法
public static RequestManager with(Context context) {
    return getRetriever(context).get(context);
  }

  public static RequestManager with(Activity activity) {
    return getRetriever(activity).get(activity);
  }

  public static RequestManager with(FragmentActivity activity) {
    return getRetriever(activity).get(activity);
  }

  public static RequestManager with(android.app.Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
  }

  public static RequestManager with(Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
  }

  public static RequestManager with(View view) {
    return getRetriever(view.getContext()).get(view);
  }
  • 会根据上面传入的参数不一样,然后调用getRetriever()Glide.get(Context)主要是检查并初始化单例对象Glide,并且判断AndroidManifest有没有配置module或者自己新建一个类添加注解GlideModule,如果有会反射获取会注册Glide中的组件和参数完成后,调用getRequestManagerRetriever()返回一个RequestManagerRetriever对象
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    return Glide.get(context).getRequestManagerRetriever();
  }
  • 返回的RequestManagerRetriever对象又调用了get(T t)方法,这也是一个重载函数,共同特点就是如果是非主线程调用Glide统一当做Application来处理,分类看一下
    Context对象会根据Context对应的实例调用不同的方法。
    其他方法共同点都是创建一个隐藏的Fragment
    如果实参是V4包中ActivityFragment会创建SupportRequestManagerFragment对象
    如果实参不是V4包中的就返回RequestManagerFragment对象
    RequestManagerFragment进行一个生命周期的绑定,如果当页面被隐藏,图片加载请求也会相应取消,从而更加节约性能。
    最终返回的是一个RequestManager对象。
 public RequestManager get(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);
  }

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

  public RequestManager get(Fragment fragment) {

    if (Util.isOnBackgroundThread()) {
      return get(fragment.getActivity().getApplicationContext());
    } else {
      FragmentManager fm = fragment.getChildFragmentManager();
      return supportFragmentGet(fragment.getActivity(), fm, fragment);
    }
  }

  public RequestManager get(Activity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
      return fragmentGet(activity, fm, null /*parentHint*/);
    }
  }

  public RequestManager get(View view) {
    if (Util.isOnBackgroundThread()) {
      return get(view.getContext().getApplicationContext());
    }

    Activity activity = findActivity(view.getContext());
    // The view might be somewhere else, like a service.
    if (activity == null) {
      return get(view.getContext().getApplicationContext());
    }

    // Support Fragments.
    if (activity instanceof FragmentActivity) {
      Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
      if (fragment == null) {
        return get(activity);
      }
      return get(fragment);
    }

    android.app.Fragment fragment = findFragment(view, activity);
    if (fragment == null) {
      return get(activity);
    }
    return get(fragment);
  }
  • 综上分析,with()就返回一个RequestManager对象,然后根据传入的参数来绑定图片加载的生命周期。

Glide如何绑定生命周期

  • 下面来看看创建的Fragment是如何和RequestManager进行生命周期绑定,由上分析可知我们会得到一个Fragment对象,在Fragment构造函数中会创建一个ActivityFragmentLifecycle,可以看到在各个生命周期函数都会调用lifecycle的函数进行监听。
  public SupportRequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
  }

  @Override
  public void onDetach() {
    super.onDetach();
    parentFragmentHint = null;
    unregisterFragmentWithRoot();
  }

  @Override
  public void onStart() {
    super.onStart();
    lifecycle.onStart();
  }

  @Override
  public void onStop() {
    super.onStop();
    lifecycle.onStop();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    lifecycle.onDestroy();
    unregisterFragmentWithRoot();
  }
  • 再来看看RequestManger的创建过程,current参数就是上面创建好的Fragment对象,通过getGlideLifecycle方法获取到刚才在构造函数中创造的ActivityFragmentLifecycle的对象,从而传递给通过工厂模式建立的RequestManager
  private RequestManager supportFragmentGet(Context context, FragmentManager fm,
      Fragment parentHint) {
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode());
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }
  • RequestManager自己实现了LifecycleListener的监听器接口,在构造函数中,在从上面Fragment传递过来的ActivityFragmentLifecycle对象添加监听器。在onStart()中启动请求,在onStop()中暂停请求,在onDestroy()做一些清理工作。
public class RequestManager implements LifecycleListener {
  RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory) {
    
    ......

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

    if (Util.isOnBackgroundThread()) {
      mainHandler.post(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);
  }

  ......

 @Override
  public void onStart() {
    resumeRequests();
    targetTracker.onStart();
  }

  @Override
  public void onStop() {
    pauseRequests();
    targetTracker.onStop();
  }


  @Override
  public void onDestroy() {
    targetTracker.onDestroy();
    for (Target<?> target : targetTracker.getAll()) {
      clear(target);
    }
    targetTracker.clear();
    requestTracker.clearRequests();
    lifecycle.removeListener(this);
    lifecycle.removeListener(connectivityMonitor);
    mainHandler.removeCallbacks(addSelfToLifecycle);
    glide.unregisterRequestManager(this);
  }
}
  • 监听器也注册了,那么进入ActivityFragmentLifecycle内部看看,发现在内部的生命周期方法中会调用监听器对应的方法。
  void onStart() {
    isStarted = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart();
    }
  }

  void onStop() {
    isStarted = false;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStop();
    }
  }

  void onDestroy() {
    isDestroyed = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onDestroy();
    }
  }
  • 经过上面的分析发现整个过程就理顺了,先创建一个Fragment对象并在构造函数中创建Lifecycle对象
    ,在通过工厂模式创建RequestManager的时候会把Lifecycle对象传递进去。
    RequestManger则会在构造函数处会将接受的Lifecycle添加监听器,RequestManager自身实现了LifecycleListener并在实现的接口方法中根据生命周期方法来启动和暂停请求。
    Lifecycle对象在添加监听器后,会在生命周期方法中回调监听器对应的方法。
    因此当Fragment会在生命周期方法中调用Lifecycle对应的生命周期方法,最终也就是在调用RequestManger中的生命周期方法,因此实现了请求和生命周期的绑定,从而可以根据生命周期来启动和暂停请求。


load()源码解析

  • 通过with()返回RequestManager对象再调用load()方法,如果没有调用asxxx()方法,都默认调用asDrawable()方法,最后创建返回了一个RequestBuilder<Drawable>对象。
  public RequestBuilder<Drawable> load(@Nullable Object model) {
    return asDrawable().load(model);
  }
  • RequestBuilder对象中,根据参数的不同,load()也有很多方法的重载,如下所示,发现共同点所有方法都会调用loadGeneric(T t)方法,下面来看看这个方法的实现。
  public RequestBuilder<TranscodeType> load(@Nullable Object model) {
    return loadGeneric(model);
  }

  public RequestBuilder<TranscodeType> load(@Nullable String string) {
    return loadGeneric(string);
  }

  public RequestBuilder<TranscodeType> load(@Nullable Uri uri) {
    return loadGeneric(uri);
  }

  public RequestBuilder<TranscodeType> load(@Nullable File file) {
    return loadGeneric(file);
  }

  public RequestBuilder<TranscodeType> load(@Nullable Integer resourceId) {
    return loadGeneric(resourceId).apply(signatureOf(ApplicationVersionSignature.obtain(context)));
  }

  public RequestBuilder<TranscodeType> load(@Nullable URL url) {
    return loadGeneric(url);
  }

  public RequestBuilder<TranscodeType> load(@Nullable byte[] model) {
    return loadGeneric(model).apply(signatureOf(new ObjectKey(UUID.randomUUID().toString()))
        .diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true));
  }
  • loadGeneric(Object model)方法很简单,将传入的model赋值给RequestBuilder的成员变量,并设置赋值的标志位为true。
  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    this.model = model;
    isModelSet = true;
    return this;
  }
  • 综上可以看出,经过load()方法会创建并返回一个RequestBuilder方法,并把load()中的参数图片源传递进去。

into()源码解析

  • 上面的load()方法返回了一个RequestBuilder方法,然后调用其中的into(),通过下面的into()进行,首先会进行是否有图片数据源和ScaleType的判断,会根据我们XML里面设置的ScaleType会做相应的设置,所以如果我们xml已经设置了,就不要在使用Glide的时候再设置一遍,最后调用另外一个重载的into()方法。
public Target<TranscodeType> into(ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      if (requestOptions.isLocked()) {
        requestOptions = requestOptions.clone();
      }
      switch (view.getScaleType()) {
        case CENTER_CROP:
          requestOptions.optionalCenterCrop();
          break;
        case CENTER_INSIDE:
          requestOptions.optionalCenterInside();
          break;
        case FIT_CENTER:
        case FIT_START:
        case FIT_END:
          requestOptions.optionalFitCenter();
          break;
        case FIT_XY:
          requestOptions.optionalCenterInside();
          break;
        case CENTER:
        case MATRIX:
        default:
          // Do nothing.
      }
    }

    return into(context.buildImageViewTarget(view, transcodeClass));
  }
  • 上述只是简单逻辑判断和设置,into方法也有两个重载,另外一个就是最后一行调用的into(Y target),而这个参数是通过context.buildImageViewTarget(view, transcodeClass)来构造的实参。
    而传入clazz参数就和我们调用asXXX()相关:
    如果调用的是asBitmap传入的是Bitmap.class就返回BitmapImageViewTarget对象。
    如果调用的是asDrawable传入的是Drawable.class,返回DrawableImageViewTarget对象。
    如果调用的是asGif传入的是Drawable的子类GifDrawable,也返回DrawableImageViewTarget对象。
    如果调用的是as(Class c),实参不是Bitmap或者不是Drawable的子类就会抛异常。
  public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {
    if (Bitmap.class.equals(clazz)) {
      return (Target<Z>) new BitmapImageViewTarget(view);
    } else if (Drawable.class.isAssignableFrom(clazz)) {
      return (Target<Z>) new DrawableImageViewTarget(view);
    } else {
      throw new IllegalArgumentException(
          "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
    }
  }
  • 下面来具体看看调用into(Y traget)方法实现,先通过buildRequest方法构建了一个Request对象,先判断target是之前已经绑定了请求,如果旧请求和新请求一样且处于请求完成或者正在请求状态就直接复用旧请求。如果不复用,就RequestManager先移除和旧请求绑定的target对象,Target再重新和Request对象进行一个绑定,调用requestManager.track(target, request)再加入请求队列,开启请求,最后返回经过处理的traget对象。
public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    requestOptions.lock();
    Request request = buildRequest(target);

    Request previous = target.getRequest();

    if (request.isEquivalentTo(previous)
      && (Preconditions.checkNotNull(previous).isComplete()
         || Preconditions.checkNotNull(previous).isRunning())) {
      request.recycle();
   
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        previous.begin();
      }
      return target;
    }

    requestManager.clear(target);
    target.setRequest(request);
    requestManager.track(target, request);

    return target;
  }
  • 通过上面分析可知into方法中最关键的两处代码分别是buildRequestrequestManager.track,一个是构建请求,一个是执行请求,搞懂了这两处代码基本就搞懂了Glide请求图片的流程。
Request request = buildRequest(target);

requestManager.track(target, request);
  • 下面来看看buildRequest内部又调用了buildRequestRecursive方法,如下所示代码省略号部分是在处理缩略图,如果对这块不关注的话,可以看到最后调用了obtainRequest方法来返回一个Request对象。
private Request buildRequest(Target<TranscodeType> target) {
    return buildRequestRecursive(target, null, transitionOptions, requestOptions.getPriority(),
        requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight());
  }

  private Request buildRequestRecursive(Target<TranscodeType> target,
      @Nullable ThumbnailRequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority, int overrideWidth, int overrideHeight) {

      ......

      return obtainRequest(target, requestOptions, parentCoordinator, transitionOptions, priority,
          overrideWidth, overrideHeight);
    }
  • 再深入进入obtainRequest方法中看看,里面又调用了SingleReuqest.obtain方法,一环嵌套一环。
 private Request obtainRequest(Target<TranscodeType> target,
      RequestOptions requestOptions, RequestCoordinator requestCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority,
      int overrideWidth, int overrideHeight) {
    requestOptions.lock();

    return SingleRequest.obtain(
        context,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        requestListener,
        requestCoordinator,
        context.getEngine(),
        transitionOptions.getTransitionFactory());
  }

  • 在这个方法里面可以看到创建了一个SingleRequest对象,并进行了初始化,初始化主要是进行成员参数的一个赋值操作。至此我们弄清楚了Glide为我们构建了一个SingleRequest的请求对象,下面来看看是请求启动的过程。
  public static <R> SingleRequest<R> obtain(
      GlideContext glideContext,
      Object model,
      Class<R> transcodeClass,
      RequestOptions requestOptions,
      int overrideWidth,
      int overrideHeight,
      Priority priority,
      Target<R> target,
      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(
        glideContext,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        requestListener,
        requestCoordinator,
        engine,
        animationFactory);
    return request;
  }
  • 通过对requestManager.track(target, request);的追踪来看看,请求是如何被启动的。track方法中调用了runRquest方法,这就是启动Request的开关。
  void track(Target<?> target, Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }
  • runRequest中请求会加入请求队列,isPaused,这个状态是根据生命周期挂钩的,如果处于暂停状态,就先将请求放入待处理队列;如果不是可以调用begin方法开始请求,这里的request就是我们上面创建并返回的SimpleRequest对象。
  public void runRequest(Request request) {
    requests.add(request);
    if (!isPaused) {
      request.begin();
    } else {
      pendingRequests.add(request);
    }
  }
  • 下面来看看SimpleRquest中的begin方法,首先判断model是否为空,model就是我们load方法中传入的对象,如果为空,就看有没有设置好的错误图片可以使用,如果有就显示错误图片,再判断是否有占位图,如果有就显示占位图,注意如果如果既设置了占位图又设置了占位图,优先显示占位图。
    如果请求已经在运行了,会抛出异常,因为不可重复启动请求。
    如果请求已经完成了,这时候又发送了一个相同的请求加载到一样的View中,就会取最新一次请求获取的资源和大小,让View重新加载一遍,就不重新进行请求了,节约资源。
    如果以上条件都符合,是一个新的合法请求,会先判断加载的长宽是否合法,如果合法会调用onSizeReady方法,如果不合法会经过计算也会调用onSizeReady方法。
    还有需要注意下面调用的onLoadStarted只是设置了占位图了,并不是真正开启来请求的加载。
  public void begin() {
    stateVerifier.throwIfRecycled();
    startTime = LogTime.getLogTime();
    if (model == null) {
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        width = overrideWidth;
        height = overrideHeight;
      }
  
      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 (status == Status.COMPLETE) {
      onResourceReady(resource, DataSource.MEMORY_CACHE);
      return;
    }

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

    if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
        && canNotifyStatusChanged()) {
      target.onLoadStarted(getPlaceholderDrawable());
    }
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logV("finished run method in " + LogTime.getElapsedMillis(startTime));
    }
  }
  • onSizeReady方法修改statusRUNNING的状态,其次获取长度和宽度,通过传入所有参数到engine.load方法,开始加载图片。
    egineEngine的对象,专门负责负责启动加载过程并管理正在显示的图片资源和已经缓存图片资源。
  public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      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);

    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.getOnlyRetrieveFromCache(),
        this);
  }
  • load方法中主要分别创建了EngineJobDecodeJob的对象
    EngineJob负责管理加载回调函数,可以添加和移除回调函数,并且当加载完成之后会调用。
    DecodeJob负责缓存和网络请求资源。
  public <R> LoadStatus load(...) {
    ......

    EngineJob<R> engineJob = engineJobFactory.build(key, isMemoryCacheable,
        useUnlimitedSourceExecutorPool);
    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);
  }
  • 来看一下engineJob.start(decodeJob)中的代码, 会调用父类ThreadPoolExecutor的的execute的方法,传入的是实现了Runnable接口的类,decodeJob实现了Runnable接口,因此调用是decodeJob中的run方法
  public void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor = decodeJob.willDecodeFromCache()
        ? diskCacheExecutor
        : getActiveSourceExecutor();
    executor.execute(decodeJob);
  }

  public void execute(Runnable command) {
    if (executeSynchronously) {
      command.run();
    } else {
      super.execute(command);
    }
  • 看一下decodeJob中的run方法,发现主要调用的是runWrapped方法
  public void run() {
    TraceCompat.beginSection("DecodeJob#run");
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      runWrapped();
    } catch (RuntimeException e) {
           .....
      }
    } finally {
           ......
    }
  }
  • runWrapped方法中有四种类型,刚开始肯定是INITIALIZE,所以分别看一下这个三个方法
  private void runWrapped() {
     switch (runReason) {
      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);
    }
  }
  • 第一个方法getNextStage(Stage.INITIALIZE)getNextStage中如果是INITIALIZE,会调用decodeCachedResource函数根据返回的bool值来判断返回的状态,由于diskCacheStrategyDiskCacheStrategy的对象,decodeCachedResource固定返回true,因此将会返回RESOURCE_CACHE状态。
  private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
      case DATA_CACHE:
        return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
      case SOURCE:
      case FINISHED:
        return Stage.FINISHED;
      default:
        throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
  }

    public boolean decodeCachedResource() {
      return true;
    }
  • 当调用完getNextStage(Stage.INITIALIZE)方法后,stage的状态变成了RESOURCE_CACHE,接下来调用getNextGenerator方法,也是根据stage的判断生成不同的对象,根据当前stageRESOURCE_CACHE状态创建了ResourceCacheGenerator对象
    这三个Generator分别代表的含义是:
    • ResourceCacheGenerator:表示从已经处理过的缓存获取数据,比如缩略图,进行放大缩小等图片处理
    • DATA_CACHE: 表示从原始缓存加载数据。
    • SOURCE: 表示从数据源加载数据
  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);
    }
  }
  • 上面知道了currentGenerator被赋值为ResourceCacheGenerator的对象,下面执行第三步runGenerators(),会发现进去了一个while循环,正常情况下前半部分条件肯定是满足的,关键后半部分
    currentGenerator.startNext()
    在ResourceCacheGenerator中``startNext主要判断的为是否缓存了处理过的图片,如果第一次加载肯定不满足,就接着调用上面的那两个方法,stage会再变成DATA_CACHEcurrentGenerator被赋值为DataCacheGenerator的对象,继续判断是否有原始缓存,如果没有stage状态变成SOURCE, currentGenerator被赋值为SourceGenerator的对象,直接调用reschedule方法,然后return退出。
    所以加载图片的顺序是处理过的缓存图片-原始缓存图片-从数据源获取图片,如网络加载。
  private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    while (!isCancelled && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }

    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
      notifyFailed();
    }
  }
  • reschedule方法中,runReason变成了SWITCH_TO_SOURCE_SERVICE,通过上面DecodeJob的函数callback就是传入的engineJobreschedule方法就是又重新调用了一遍executor.execute(decodeJob),也就执行了run方法,又回到了runWrapped方法中,不过这时的runReason已经是SWITCH_TO_SOURCE_SERVICE,所以直接执行runGenerators方法,即开始执行
    SourceGeneratorstartNext方法
  public void reschedule() {
    runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
    callback.reschedule(this);
  }
  • 下面来看看SourceGenerator中的startNext方法
  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;
  }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容