重学Android——Glide4.x源码分析(1)

重学Android——Glide4.x源码分析(2)

Glide4.x

先来说下世面上常用的三种图片加载框架Picasso,Glide,Fresco

Picasso与Glide相比:

  • 相似——api上的调用差不多,都支持内存缓存,glide是picasso的升级,性能有一定的提升
  • 差异
    • 缓存不同,picasso2级缓存,没有磁盘缓存,Glide三级缓存,内存-磁盘-网络的优先级加载黑乎乎。
    • Picasso默认加载的图片格式是ARGB-8888,Glide默认是RGB-565,内存开销节省小一半
    • Picasso是加载全尺寸图片到内存中,下次在任何imageView中加载图片时,先取全尺寸图片,重新调整大小,再存缓存。而Glide是按ImageView的大小缓存的,为每种大小缓存一次。Glide这种方式是空间换时间,大小几乎是picasso的2倍
    • 生命周期问题,Glide的with方法图片加载会和Activity与Fragment的生命周期一致
    • Glide可以加载GIF
    • Picasso包特别小,100k左右,方法法为850,glide大概500k,2700个方法。

Fresco

  • 优点:
    • 图片存储在安卓系统匿名共享内存区,而不是虚拟机的堆内存,图片的中间缓冲数据也存放在本地堆内存,所以应用有更多的内存空间使用。不容易OOM,减少GC回收
    • 渐近式加载,支持图片从模糊到清晰,用户体验极好
    • 图片可以以任意为中心点显示在ImageView
    • JPEG图片改变大小也是在native进行,不在虚拟机堆内存,同样减少OOM
    • 对GIF支持友好
  • 缺点
    • 包太大,2-3M
    • 用法复杂
    • 底层都是C/C++,源码阅读有挑战性
小结

Glide能做Picasso能做的所有事情,更快,能处理大型图片流,一般Glide是首选;Fresco当使用图片非常多的应用时,它的优势非常明显

Glide的基本使用

    implementation ("com.github.bumptech.glide:glide:4.9.0") {
        exclude group: "com.android.support"
    }
    annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
复制代码
    Glide.with(this)
        .load("http://pic37.nipic.com/20140113/8800276_184927469000_2.png")
        .into(imageView);

<uses-permission android:name="android.permission.INTERNET" />
复制代码

需要注意的是,我们在Android9.0以上使用,用的http请求的话,需要在AndroidMainfest中

    <application
        ...
        android:usesCleartextTraffic="true">
复制代码

原因是android9.0以后,默认禁止http请求的。

Glide源码

Glide.with(实例化Glide并获取RequestManager)

先看Glide.with()方法

  @NonNull
  public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }

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

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

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

  @SuppressWarnings("deprecation")
  @Deprecated
  @NonNull
  public static RequestManager with(@NonNull android.app.Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
  }

  @NonNull
  public static RequestManager with(@NonNull View view) {
    return getRetriever(view.getContext()).get(view);
  }
复制代码

可以看到,with方法有多个重载方法,而且都是先调用了getRetriever这个方法,那么我们先看这个方法的源码

  @NonNull
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    ...
    return Glide.get(context).getRequestManagerRetriever();
  }
复制代码

从源码看,直接是调用Glide的get()方法,然后再调用getRequestManagerRetriever

先看get方法

  @NonNull
  public static Glide get(@NonNull Context context) {
    if (glide == null) {
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context);
        }
      }
    }

    return glide;
  }
复制代码

一看原来Glide是单例,只有第一次会实例化,通过Builder模式实例化Glide对象,初始化后调用getRequestManagerRetriever方法来得到RequestManagerRetriever对象。

生命周期管理

那么问题又回到了getRetriever(xxx).get(xxx);这里,当getRetriever得到了RequestManagerRetriever对象,我们继续看后面的get方法

    //get方法也和with一样,有多个对应的重载
	@NonNull
    public 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)) {
            //直接返回ApplicationManager
            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());
            }
        }
		//传入的context为ApplicationContext
        return getApplicationManager(context);
    }

	//get(Activity/fragement)逻辑都差不多的,这里只拿getFragmentActivity来讲
    @NonNull
    public RequestManager get(@NonNull FragmentActivity activity) {
        if (Util.isOnBackgroundThread()) {
            //后台时,就调用get(context)
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            //前台可见,创建一个FragmentManager
            FragmentManager fm = activity.getSupportFragmentManager();
            return supportFragmentGet(
                activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
        }
    }

    @NonNull
    private RequestManager supportFragmentGet(
        @NonNull Context context,
        @NonNull FragmentManager fm,
        @Nullable Fragment parentHint,
        boolean isParentVisible) {
        //获取RequestManager
        SupportRequestManagerFragment current =
            getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            // TODO(b/27524013): Factor out this Glide.get() call.
            Glide glide = Glide.get(context);
            //如果得到requestManager为空,创建requestManager,并把Lifecycle传了进去
            requestManager =
                factory.build(
                glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
            //缓存这个requestManager
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }

	//创建并添加一个SupportRequestManagerFragment
    @NonNull
    private SupportRequestManagerFragment getSupportRequestManagerFragment(
        @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
        SupportRequestManagerFragment current =
            (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
            current = pendingSupportRequestManagerFragments.get(fm);
            if (current == null) {
                current = new SupportRequestManagerFragment();
                current.setParentFragmentHint(parentHint);
                if (isParentVisible) {
                    current.getGlideLifecycle().onStart();
                }
                pendingSupportRequestManagerFragments.put(fm, current);
                //在这里,使用fragmentManager添加了一个隐藏的无界面Fragment
                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
            }
        }
        return current;
    }
复制代码

可以看到,get方法的重载方法很多,但是核心都是一样的的,就是返回两种requestManager,1. ApplicationManager,它的生命周期与应用同步,应用退出,Glide也退出;2. 附加在Fragment之上的requestManager,通过这个fragment,绑定了对应的生命周期,这样就可以在Activity销毁时往上加载了,RxPermission也是这么设计的。

public class SupportRequestManagerFragment extends Fragment {
  private static final String TAG = "SupportRMFragment";
  private final ActivityFragmentLifecycle lifecycle;  
  ...
  @Override
  public void onAttach(Context context) {
    super.onAttach(context);
    try {
      registerFragmentWithRoot(getActivity());
    } catch (IllegalStateException e) {
      // OnAttach can be called after the activity is destroyed, see #497.
      if (Log.isLoggable(TAG, Log.WARN)) {
        Log.w(TAG, "Unable to register fragment with root", e);
      }
    }
  }

  @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();
  }
...
}
复制代码

可以看到,SupportRequestManagerFragment就是这么设计的,注入了一个生命周期监听器ActivityFragmentLifecycle,并在Fragment的各个生命周期中,调用了对应的方法。

class ActivityFragmentLifecycle implements Lifecycle {
  ...
  @Override
  public void addListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.add(listener);

    if (isDestroyed) {
      listener.onDestroy();
    } else if (isStarted) {
      listener.onStart();
    } else {
      listener.onStop();
    }
  }

  @Override
  public void removeListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.remove(listener);
  }

  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();
    }
  }
}
复制代码

可以看到,在ActivityFragmentLifecycle会紧接着调用lifecycleListener监听器,而这个监听器其实就是RequestManager。

最后,可以看到,生命周期已与requestManager进行了绑定。

RequestBuilder
load

接下来我们看load方法的源码

  public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }
复制代码

先来看前面的asDrawable

  public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
  public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }
复制代码

其实就相当于new RequestBuilder,那再看load

  public RequestBuilder<TranscodeType> load(@Nullable String string) {
    return loadGeneric(string);
  }
  @NonNull
  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    this.model = model;
    isModelSet = true;
    return this;
  }
复制代码

可以看到load方法非常简单,其实是创建了RequestBuilder,并把传递进来的参数url赋值给RequestBuilder中。

into方法实现资源加载并设置到target中

再看into方法

  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    BaseRequestOptions<?> requestOptions = this;
    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.
      //这些都与ImageView的scaleType相关,是转换逻辑,与我们关心的代码流程无关,可以不用关心
      switch (view.getScaleType()) {
        case CENTER_CROP:
          requestOptions = requestOptions.clone().optionalCenterCrop();
          break;
        case CENTER_INSIDE:
          requestOptions = requestOptions.clone().optionalCenterInside();
          break;
        case FIT_CENTER:
        case FIT_START:
        case FIT_END:
          requestOptions = requestOptions.clone().optionalFitCenter();
          break;
        case FIT_XY:
          requestOptions = requestOptions.clone().optionalCenterInside();
          break;
        case CENTER:
        case MATRIX:
        default:
          // Do nothing.
      }
    }

    //真正执行的代码在这
    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        Executors.mainThreadExecutor());
  }
复制代码

分析源码可以知道,它的内部调用了into的重载方法

我们先看里面的参数方法glideContext.buildImageViewTarget(view, transcodeClass),

  @NonNull
  public <X> ViewTarget<ImageView, X> buildImageViewTarget(
      @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }
  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);
    } else {
      throw new IllegalArgumentException(
          "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
    }
  }
复制代码

可以看到,返回了ViewTarger,还记得上面我们看到的asDrawable么,说明是DrawableImageViewTarget,接下来再看外层的into方法

  private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor) {
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

      //创建request
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
	//获取targert之前的请求任务(如果有的话)
    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
        //新构建的request上一个相等,并且设置了缓存以及没有执行完成
        //释放新的request
      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()) {
          //当旧的request没有在运行。执行它的begin
        // 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;
    }

      // 清除先Target之前的所有任务并释放资源
    requestManager.clear(target);
      //把新的request设置给target
    target.setRequest(request);
    //在这里执行request,下载图片任务
    requestManager.track(target, request);

    return target;
  }

  private boolean isSkipMemoryCacheWithCompletePreviousRequest(
      BaseRequestOptions<?> options, Request previous) {
      //是否设置缓存以及上一次是否执行完成
    return !options.isMemoryCacheable() && previous.isComplete();
  }
复制代码

这里主要做了两件事:

  1. 通过buildRequest构建了一个request
  2. 获取target的上一个request对象,与新的request对比,并检测是否采用了缓存及target的上次请求是否完成
    1. 两个对象相等,并且options采用了缓存或target上一次没有请求完,则将新的request回收,并判断target的request是否还在运行,没有的话begin,并返回
    2. 两个对象不相等,或者option没有使用缓存和target请求完成了,清除target的之间设置,并将新的request对象设置给target,通过track方法启动request请求。

再来看requestManager的track方法

  synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }

  public void track(@NonNull Target<?> target) {
    targets.add(target);
  }

  public void runRequest(@NonNull Request request) {
    requests.add(request);
    if (!isPaused) {
        //当处于前台可见时,调用request的begin
      request.begin();
    } else {
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
        //先不执行request,只把它加入到一个准备队列
      pendingRequests.add(request);
    }
  }
复制代码

可的看到,track方法是先将target添加到targetTracker类的targets集合中,然后运行request的begin方法。

到这里,其实图片加载网络资源的流程已经完成了大半了。接下来接着看如何加载资源并显示到target上的。

Request实现加载资源及显示

我们直接点request.begin方法去跟踪源码,会发现Request只是一个接口,所以我们要找到它的实现类。

那么我们再看上面的创建request方法

  private Request buildRequest(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {
    return buildRequestRecursive(
        target,
        targetListener,
        /*parentCoordinator=*/ null,
        transitionOptions,
        requestOptions.getPriority(),
        requestOptions.getOverrideWidth(),
        requestOptions.getOverrideHeight(),
        requestOptions,
        callbackExecutor);
  }

  //参数是真鸡儿长
  private Request buildRequestRecursive(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {
	...

    //关键代码
    Request mainRequest =
        buildThumbnailRequestRecursive(
            target,
            targetListener,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight,
            requestOptions,
            callbackExecutor);

    if (errorRequestCoordinator == null) {
      return mainRequest;
    }

    ...
        //如果有设置错误时的处理逻辑
    return errorRequestCoordinator;
  }
复制代码

可以看到,真正的核心代码在buildThumbnailRequestRecursive方法

	//这个方法结构其实很简单,但是参数太多,所以把参数省略再看
    private Request buildThumbnailRequestRecursive(
        ...) {
        //默认的thumbnailBuilder就是空的,除非手动调用RequestBuilder类的thumbnail方法
        //否则这个if代码块永远执行不到
        if (thumbnailBuilder != null) {
            // Recursive case: contains a potentially recursive thumbnail request builder.
            if (isThumbnailBuilt) {
                throw new IllegalStateException("You cannot use a request as both the main request and a "
                                                + "thumbnail, consider using clone() on the request(s) passed to thumbnail()");
            }

            TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
                thumbnailBuilder.transitionOptions;

            // Apply our transition by default to thumbnail requests but avoid overriding custom options
            // that may have been applied on the thumbnail request explicitly.
            if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
                thumbTransitionOptions = transitionOptions;
            }

            //缩略图权限
            Priority thumbPriority = thumbnailBuilder.isPrioritySet()
                ? thumbnailBuilder.getPriority() : getThumbnailPriority(priority);

            //缩略图宽高
            int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth();
            int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight();
            //宽高检验
            if (Util.isValidDimensions(overrideWidth, overrideHeight)
                && !thumbnailBuilder.isValidOverride()) {
                thumbOverrideWidth = requestOptions.getOverrideWidth();
                thumbOverrideHeight = requestOptions.getOverrideHeight();
            }

            //缩略图请求协议器,同时协调原图与缩略图的request
            ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
            //原图请求
            Request fullRequest =
                obtainRequest(...);
            isThumbnailBuilt = true;
            // Recursively generate thumbnail requests.
            //调用buildRequestRecursive,还是会调到buildThumbnailRequestRecursive,这是个递归方法
            //递归生成缩略图请求
            Request thumbRequest =
                thumbnailBuilder.buildRequestRecursive(...);
            isThumbnailBuilt = false;
            //把这两个request包装到ThumbnailRequestCoordinator中
            coordinator.setRequests(fullRequest, thumbRequest);
            return coordinator;
        } else if (thumbSizeMultiplier != null) {
            //根据指定的缩放系数加载缩略图
            // Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
            ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
            Request fullRequest =
                obtainRequest(...);
            BaseRequestOptions<?> thumbnailOptions =
                requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);

            Request thumbnailRequest =
                obtainRequest(...);

            coordinator.setRequests(fullRequest, thumbnailRequest);
            return coordinator;
        } else {
            //只加载原图
            // Base case: no thumbnail.
            return obtainRequest(...);
        }
    }
复制代码

可以看到,在buildThumbnailRequestRecursive主要做了有无缩略图的判断,然后再进行加载,最后调用了obtainRequest方法

  private Request obtainRequest(
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> requestOptions,
      RequestCoordinator requestCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      Executor callbackExecutor) {
    return SingleRequest.obtain(
        context,
        glideContext,
        model,//对应load(url),比如一个图片地址
        transcodeClass,
        requestOptions,
        overrideWidth,//宽
        overrideHeight,//高
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),//全局加载引擎
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }
复制代码

这个方法通过SingleReques类的方法obtain去创建一个Request对象,所以,它就是我们要找的requst,那么看它的begin方法

开启资源加载任务
  @Override
  public synchronized 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;
      //如果Target的宽高已经获取并合法,就开始下一步
    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 (IS_VERBOSE_LOGGABLE) {
      logV("finished run method in " + LogTime.getElapsedMillis(startTime));
    }
  }

复制代码

可以看到,begin方法经过一系列的判断,当status是RUNNING或者WAITING_FOR_SIZE状态,并且需要设置占位图时,会调用onLoadStarted设置占位图,当状态是COMPLETE时,会执行onResourceReady方法并返回。

 @Override
  public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
    stateVerifier.throwIfRecycled();
    loadStatus = null;
    ...
	//判断是否需要设置资源,如果不需要就直接释放并设置状态为COMPLETE
    if (!canSetResource()) {
      releaseResource(resource);
      // We can't put the status to complete before asking canSetResource().
      status = Status.COMPLETE;
      return;
    }

      //执行方法
    onResourceReady((Resource<R>) resource, (R) received, dataSource);
  }
复制代码

上面省略了一大段加载失败的代码,直接来看onResourceReady的重载方法。

  private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
    // We must call isFirstReadyResource before setting status.
    boolean isFirstResource = isFirstReadyResource();
    status = Status.COMPLETE;
    this.resource = resource;
    ...
    try {
      boolean anyListenerHandledUpdatingTarget = false;
      if (requestListeners != null) {
        for (RequestListener<R> listener : requestListeners) {
          anyListenerHandledUpdatingTarget |=
              listener.onResourceReady(result, model, target, dataSource, isFirstResource);
        }
      }
      anyListenerHandledUpdatingTarget |=
          targetListener != null
              && targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
		
      //设置资源及动画相关的信息
      if (!anyListenerHandledUpdatingTarget) {
        Transition<? super R> animation =
            animationFactory.build(dataSource, isFirstResource);
          //这个target有多个,比如DrawableImageViewTarget 
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

      //最后通知加载成功
    notifyLoadSuccess();
  }
复制代码

可以看到,当状态为COMPLETE时,就是把当前result设置到当前的target上,并通知加载成功(做一些加载成功后的清理工作)。

上面是COMPLETE时的状态,那么不是这个状态时呢?会执行到onSizeReady方法

  @Override
  public synchronized 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);

    if (IS_VERBOSE_LOGGABLE) {
      logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
    }
      //加载流程
    loadStatus =
        engine.load(
            glideContext,
            model,//对应rul,图片地址
            requestOptions.getSignature(),
            this.width,
            this.height,
            requestOptions.getResourceClass(),//默认是Object.class
            transcodeClass,//默认是Drawable.class
            priority,
            requestOptions.getDiskCacheStrategy(),//缓存策略,默认是AUTOMATIC
            requestOptions.getTransformations(),
            requestOptions.isTransformationRequired(),
            requestOptions.isScaleOnlyOrNoTransform(),
            requestOptions.getOptions(),
            requestOptions.isMemoryCacheable(),
            requestOptions.getUseUnlimitedSourceGeneratorsPool(),
            requestOptions.getUseAnimationPool(),
            requestOptions.getOnlyRetrieveFromCache(),
            this,
            callbackExecutor);
  }
复制代码

可以看到,调用了Engine的load方法,关于加载图片的加载机制,我们下一篇再讲,今天先就讲到这。

总结

这一篇主要分析Glide.with().load().into()的简单流程

  1. Glide类作为入口类,调用静态方法with(),实例化了Glide这个单例,取得RequestManager对象并返回
  2. RequestManager去管理Request请求,根据Activity或Fragment生命周期,管理request请求,包括:onStop,onStart,onDestory,pauseRequest,resumeRequests等,并可以设置加载资源要返回的资源类型,Bitmap,Drawable,Gif。通过调用load()、asBitmap()、asFile()等方法均返回一个RquestBuilder对象,将资源的请求处理移交给了RequestBuilder,实现将功能分离,模块化处理。
  3. RquestBuilder处理资源加载请求,调用apply()方法传入RequestOptions对象进行一些选项设置;调用transition()方法实现资源加载显示时过度动画;最后调用into()方法,去构建Rquest对象或使用Target设置过的Request对象,调用Rquest的对象方法begin()开启加载请求。
  4. 开启请求后的工作就移交到Request类中,加载完成后,Request调用onResourceReady()方法去判断加载结果,若加载成功,调用Target类的onReadySuccess()方法设置资源,调用RequestCoordinator中方法onRequestSuccess()执行加载成功后的资源清理工作。若加载失败,Request直接调用notifyLoadFailed()方法,将清理资源工作移交给RequestCoordinator类处理。

参考


我的CSDN

下面是我的公众号,欢迎大家关注我

转载于:https://juejin.im/post/5d013eecf265da1b7f2977f4

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值