美文网首页
Glide 源码解析 ----- android source

Glide 源码解析 ----- android source

作者: morn___ | 来源:发表于2018-04-27 14:06 被阅读0次

    作为google主推的一款图片加载框架,从glide3.x 到glide4.x加入apt的注解编译;详细的使用可以详见官方文档
    [Glide v4] https://muyangmin.github.io/glide-docs-cn/
    ps:之前在csdn 简书第一篇 欢迎大家浏览

    • 首先来看Glide的基本使用:

    (1)支持Memory和Disk图片缓存。
    (2)支持gif和webp格式图片。
    (3)根据Activity/Fragment生命周期自动管理请求。
    (4)使用Bitmap Pool可以使Bitmap复用。*
    (5)对于回收的Bitmap会主动调用recycle,减小系统回收压力。

           GlideApp.with(this)
                //.asBitmap()   --- 转换为bitmap
                //.asDrawable() ---- 转换为drawable
                .asGif() --- 转换为gif
                .load(url)
                .placeholder(R.mipmap.ic_launcher_round)
                .error(R.mipmap.ele)
                .fitCenter()
                //.fallback()当请求图片为null的时候
                .into(mIv);
    

    在Glide v4中通过注解会在build 下apt生成部分外部文件 来操作glide,大大提高glide的可定制性,可以去看文章开头的官网地址来看使用方式;下面的解析以v4为准

    1. 首先来看glide的初始化:

    GlideApp.with(this)


    GlideApp:
      @NonNull
      public static GlideRequests with(@NonNull FragmentActivity arg0) {
        return (GlideRequests) Glide.with(arg0);
      }
    
    Glide:
      @NonNull
      public static RequestManager with(@NonNull FragmentActivity activity) {
        return getRetriever(activity).get(activity);
      }
    

    这里是对Glide的初始化,以及对生命周期的管理:
    核心代码:

        getRetriever(activity).get(activity);
    

    其中 getRetriever(activity)是glide的初始化

     @NonNull
      private static RequestManagerRetriever getRetriever(@Nullable Context context) {
        // Context could be null for other reasons (ie the user passes in null), but in practice it will
        // only occur due to errors with the Fragment lifecycle.
        Preconditions.checkNotNull(
            context,
            "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
                + "returns null (which usually occurs when getActivity() is called before the Fragment "
                + "is attached or after the Fragment is destroyed).");
        return Glide.get(context).getRequestManagerRetriever();
      }
    

    这里主要来看Glide.get(context):

    @NonNull
      public static Glide get(@NonNull Context context) {
        if (glide == null) {
          synchronized (Glide.class) {
            if (glide == null) {
              checkAndInitializeGlide(context);
            }
          }
        }
    
        return glide;
      }
    
     private static void checkAndInitializeGlide(@NonNull Context context) {
        // In the thread running initGlide(), one or more classes may call Glide.get(context).
        // Without this check, those calls could trigger infinite recursion.
        if (isInitializing) {
          throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
              + " use the provided Glide instance instead");
        }
        isInitializing = true;
        initializeGlide(context);
        isInitializing = false;
      }
    
    
    private static void initializeGlide(@NonNull Context context) {
        initializeGlide(context, new GlideBuilder());
      }
    
      @SuppressWarnings("deprecation")
      private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
        ......省略部分代码
    
        Glide glide = builder.build(applicationContext);
    
    
        for (com.bumptech.glide.module.GlideModule module : manifestModules) {
          module.registerComponents(applicationContext, glide, glide.registry);
        }
        if (annotationGeneratedModule != null) {
          annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
        }
        applicationContext.registerComponentCallbacks(glide);
        Glide.glide = glide;
      }
    
    

    在initializeGlide中有一个构建中模式的glide初始化,见怪不怪这是glide的真正初始化: Glide glide = builder.build(applicationContext);
    继续深入:

    @NonNull
      public Glide build(@NonNull Context context) {
        if (sourceExecutor == null) {
          sourceExecutor = GlideExecutor.newSourceExecutor();
        }
    
        if (diskCacheExecutor == null) {
          diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
        }
    
        if (animationExecutor == null) {
          animationExecutor = GlideExecutor.newAnimationExecutor();
        }
    
        if (memorySizeCalculator == null) {
          memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
        }
    
        if (connectivityMonitorFactory == null) {
          connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
        }
    
        if (bitmapPool == null) {
          int size = memorySizeCalculator.getBitmapPoolSize();
          if (size > 0) {
            bitmapPool = new LruBitmapPool(size);
          } else {
            bitmapPool = new BitmapPoolAdapter();
          }
        }
    
        if (arrayPool == null) {
          arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
        }
    
        if (memoryCache == null) {
          memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
        }
    
        if (diskCacheFactory == null) {
          diskCacheFactory = new InternalCacheDiskCacheFactory(context);
        }
    
        if (engine == null) {
          engine =
              new Engine(
                  memoryCache,
                  diskCacheFactory,
                  diskCacheExecutor,
                  sourceExecutor,
                  GlideExecutor.newUnlimitedSourceExecutor(),
                  GlideExecutor.newAnimationExecutor(),
                  isActiveResourceRetentionAllowed);
        }
    
        RequestManagerRetriever requestManagerRetriever =
            new 
    (requestManagerFactory);
    
        return new Glide(
            context,
            engine,
            memoryCache,
            bitmapPool,
            arrayPool,
            requestManagerRetriever,
            connectivityMonitorFactory,
            logLevel,
            defaultRequestOptions.lock(),
            defaultTransitionOptions);
      }
    

    在这里glide初始化就完全初始化完毕:
    相关图片线程池---bitmapPool
    图片加载器engin等的初始化 等就基本完成了
    当然没有必要去细究其具体的参数,主要是理解其思想;

    ok~到这里 glide的初始化完毕,下面通过glide的api

        getRetriever(activity).get(activity);
    

    看到其中的get方法没有,这里是glide的一个亮点;通过传入activity/fragment/或者view等来控制图片加载的周期来提高其性能:
    下面看具体的代码:

    
      @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)) {
          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);
      }
    
      @NonNull
      public RequestManager get(@NonNull FragmentActivity activity) {
        if (Util.isOnBackgroundThread()) {
          return get(activity.getApplicationContext());
        } else {
          assertNotDestroyed(activity);
          FragmentManager fm = activity.getSupportFragmentManager();
          return supportFragmentGet(activity, fm, null /*parentHint*/);
        }
      }
    
      @NonNull
      public RequestManager get(@NonNull Fragment fragment) {
        Preconditions.checkNotNull(fragment.getActivity(),
              "You cannot start a load on a fragment before it is attached or after it is destroyed");
        if (Util.isOnBackgroundThread()) {
          return get(fragment.getActivity().getApplicationContext());
        } else {
          FragmentManager fm = fragment.getChildFragmentManager();
          return supportFragmentGet(fragment.getActivity(), fm, fragment);
        }
      }
    
      @NonNull
      public RequestManager get(@NonNull Activity activity) {
        if (Util.isOnBackgroundThread()) {
          return get(activity.getApplicationContext());
        } else {
          assertNotDestroyed(activity);
          android.app.FragmentManager fm = activity.getFragmentManager();
          return fragmentGet(activity, fm, null /*parentHint*/);
        }
      }
    
      @NonNull
      public RequestManager get(@NonNull View view) {
        if (Util.isOnBackgroundThread()) {
          return get(view.getContext().getApplicationContext());
        }
    
        Preconditions.checkNotNull(view);
        Preconditions.checkNotNull(view.getContext(),
            "Unable to obtain a request manager for a view without a Context");
        Activity activity = findActivity(view.getContext());
        // The view might be somewhere else, like a service.
        if (activity == null) {
          return get(view.getContext().getApplicationContext());
        }
    
        // Support Fragments.
        // Although the user might have non-support Fragments attached to FragmentActivity, searching
        // for non-support Fragments is so expensive pre O and that should be rare enough that we
        // prefer to just fall back to the Activity directly.
        if (activity instanceof FragmentActivity) {
          Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
          return fragment != null ? get(fragment) : get(activity);
        }
    
        // Standard Fragments.
        android.app.Fragment fragment = findFragment(view, activity);
        if (fragment == null) {
          return get(activity);
        }
        return get(fragment);
      }
    

    可以看到glide 支持的是fragmentActivity/activity/fragment/view/context;其中view是通过判断其所依托的碎片来进行周期管理;
    殊途同归,下面以activity为例来简单剖析:

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

    大致可以猜出一二,这里是依托于activity之下碎片fragment来进行周期的回调;同理fragment也是这样fragment.getChildFragmentManager();

     @NonNull
      private RequestManager supportFragmentGet(@NonNull Context context, @NonNull FragmentManager fm,
          @Nullable Fragment parentHint) {
        SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
          // TODO(b/27524013): Factor out this Glide.get() call.
          Glide glide = Glide.get(context);
          requestManager =
              factory.build(
                  glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
          current.setRequestManager(requestManager);
        }
        return requestManager;
      }
    

    上面代码第一行: SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);

    @NonNull
      RequestManagerFragment getRequestManagerFragment(
          @NonNull final android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint) {
        RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
          current = pendingRequestManagerFragments.get(fm);
          if (current == null) {
            current = new RequestManagerFragment();
            current.setParentFragmentHint(parentHint);
            pendingRequestManagerFragments.put(fm, current);
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
            handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
          }
        }
        return current;
      }
    
    
     @Override
      public boolean handleMessage(Message message) {
        boolean handled = true;
        Object removed = null;
        Object key = null;
        switch (message.what) {
          case ID_REMOVE_FRAGMENT_MANAGER:
            android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
            key = fm;
            removed = pendingRequestManagerFragments.remove(fm);
            break;
          case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
            FragmentManager supportFm = (FragmentManager) message.obj;
            key = supportFm;
            removed = pendingSupportRequestManagerFragments.remove(supportFm);
            break;
          default:
            handled = false;
            break;
        }
        if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
          Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
        }
        return handled;
      }
    

    在getRequestManagerFragment中通过创建RequestManagerFragment并且添加到activity中,同时把RequestManagerFragments从缓存队列pendingRequestManagerFragments中移除,进行加载;

    然后继续看supportFragmentGet:
    获取到SupportRequestManagerFragment,然后通过SupportRequestManagerFragment获取requestManager: RequestManager requestManager = current.getRequestManager();如果为空则通过

    factory.build(
                  glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
    

    进行创建最后set到SupportRequestManagerFragment中;注意其参数.current.getGlideLifecycle()其实就是这个接口来回调SupportRequestManagerFragment的周期方法进而进行周期的控制;

    1. 首先来看glide的相关配置:图形属性,

    GlideApp.with(this)
    .load(url)


    首先来看url的加载:

    #GlideApp
      @Override
      @NonNull
      @CheckResult
      public GlideRequest<TranscodeType> load(@Nullable String arg0) {
        return (GlideRequest<TranscodeType>) super.load(arg0);
      }
    
    #Glide  --- 多种实现类
     @NonNull
      @Override
      @CheckResult
      public RequestBuilder<TranscodeType> load(@Nullable String string) {
        return loadGeneric(string);
      }
    
      @NonNull
      @CheckResult
      @Override
      public RequestBuilder<TranscodeType> load(@Nullable Uri uri) {
        return loadGeneric(uri);
      }
    
    ....
    
    
    @NonNull
      private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
        this.model = model;
        isModelSet = true;
        return this;
      }
    
    
    

    由以上代码中可以看到load有很多实现类,最后都是在RequestBuilder中初始化参数model,在into的时候进行加载;
    接着看Glide对图片属性的支持:

    GlideApp.with(this)
    //.asBitmap() --- 对图片格式的编码转化
    //.asDrawable()
    .asGif()
    .miniThumb(100)
    .placeholder(R.mipmap.ic_launcher_round) --- 占位图
    .error(R.mipmap.ele) ---- 错误之后的显示图
    .fitCenter() --- 图片显示样式
    //.fallback()当请求图片为null的时候

    一般Glide通过一系列链式来配置图片的属性,和加载的属性;当然也可以通过RequestOption来自定义(把相关配置apply进去),最后把RequestOption apply到RequstBuilder中;
    举一例.asGif():

    #GlideApp
     @Override
      @NonNull
      @CheckResult
      public GlideRequest<GifDrawable> asGif() {
        return (GlideRequest<GifDrawable>) super.asGif();
      }
    
    #Glide
      private static final RequestOptions DECODE_TYPE_GIF = decodeTypeOf(GifDrawable.class).lock();
    
     @NonNull
      @CheckResult
      public RequestBuilder<GifDrawable> asGif() {
        return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
      }
    
    
    

    从以上代码可以看到decodeTypeOf(GifDrawable.class).lock();转化为一个GifDrawable之后apply到RequstBuilder中,看到这里是不是感觉RequstBuilder就是一个总指挥,主导Glide的大部分行为(如下 附decodeTypeOf的源码)

      @NonNull
      @CheckResult
      public static RequestOptions decodeTypeOf(@NonNull Class<?> resourceClass) {
        return new RequestOptions().decode(resourceClass);
      }
    

    当这里我们对RequestOptions这个原型有了一定的了解;
    当然你可以参阅文章开头的Glide v4官网来看其使用,慢慢体会这个思想;

    1. 最后看glide的加载与最终实现:

    GlideApp.with(this)
    .load(url);
    同样由浅入深来看:

    @NonNull
      public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
        Util.assertMainThread();
        Preconditions.checkNotNull(view);
    
        RequestOptions requestOptions = this.requestOptions;
        if (!requestOptions.isTransformationSet()
            && requestOptions.isTransformationAllowed()
            && view.getScaleType() != null) {
          // Clone in this method so that if we use this RequestBuilder to load into a View and then
          // into a different target, we don't retain the transformation applied based on the previous
          // View's scale type.
          switch (view.getScaleType()) {
            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);
      }
    

    首先是对图片的现实样式进行设置,通过目标getScaleType来同步requstoption的相关设置,继续看:
    glideContext.buildImageViewTarget(view, transcodeClass), null,requestOptions);
    这里的三个参数分别是目标target,targetListener,requestOptions;继续看源码:

    private <Y extends Target<TranscodeType>> Y into(
          @NonNull Y target,
          @Nullable RequestListener<TranscodeType> targetListener,
          @NonNull RequestOptions options) {
        Util.assertMainThread();
        Preconditions.checkNotNull(target);
        if (!isModelSet) {
          throw new IllegalArgumentException("You must call #load() before calling #into()");
        }
    
        options = options.autoClone();
        Request request = buildRequest(target, targetListener, options);
    
        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);
        requestManager.track(target, request);
    
        return target;
      }
    

    其中:

     options = options.autoClone();
        Request request = buildRequest(target, targetListener, options);
    
        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);
        requestManager.track(target, request);
    

    接着看 requestManager.track(target, request);其他就是清楚和设置requst的代码,一目了然:

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

    注意在Glide中是可以设置优先级的,在 targetTracker.track(target);中把目标图片统一通过targets来管理,而targets是Set集合是具有排序功能的;
    继续看 requestTracker.runRequest(request);源码:

      public void runRequest(@NonNull Request request) {
        requests.add(request);
        if (!isPaused) {
          request.begin();
        } else {
          pendingRequests.add(request);
        }
      }
    

    到这里可以看到当没有onPause时候requst会开始加载,onPause时候加入缓存队列等待;当然我们看到了Glide所谓的周期管理:追根溯源:

    1.在glide.with中提到activity中创建了SupportRequestManagerFragment,并通过传入 current.getGlideLifecycle()来current.setRequestManager(requestManager);

    2.在SupportRequestManagerFragment中通过会调lifecycle来监听其周期:
    eg:

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

    3.然而这个lifecycle是ActivityFragmentLifecycle,在RequstManger的构造中:
    lifecycle.addListener(this);然后在周期的会调是实现方法中用targetTracker管理起来:
    eg:

     # requstManger
      @Override
      public void onStop() {
        pauseRequests();
        targetTracker.onStop();
      }
    
       public void pauseRequests() {
        Util.assertMainThread();
        requestTracker.pauseRequests();
      }
    
    #RequstTracker
     public void pauseRequests() {
        isPaused = true;
        for (Request request : Util.getSnapshot(requests)) {
          if (request.isRunning()) {
            request.pause();
            pendingRequests.add(request);
          }
        }
      }
    

    ok~ 到了这里就明白了 之前讲到

     public void runRequest(@NonNull Request request) {
        requests.add(request);
        if (!isPaused) {
          request.begin();
        } else {
          pendingRequests.add(request);
        }
      }
    

    这里的周期判断就已经明了了,在Glide中SingleRequst比较常用,那么来看他的begin源码:

     @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)) {
          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));
        }
      }
    
    

    以上代码中Glide对加载状态进行了判断,并且对其width和height进行重新处理,让然一些策略是不错的,比如:

      if (status == Status.COMPLETE) {
          onResourceReady(resource, DataSource.MEMORY_CACHE);
          return;
        }
    
     @SuppressWarnings("unchecked")
      @Override
      public void onResourceReady(Resource<?> resource, DataSource dataSource) {
        stateVerifier.throwIfRecycled();
        loadStatus = null;
        if (resource == null) {
          GlideException exception = new GlideException("Expected to receive a Resource<R> with an "
              + "object of " + transcodeClass + " inside, but instead got null.");
          onLoadFailed(exception);
          return;
        }
    
        Object received = resource.get();
        if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
          releaseResource(resource);
          GlideException exception = new GlideException("Expected to receive an object of "
              + transcodeClass + " but instead" + " got "
              + (received != null ? received.getClass() : "") + "{" + received + "} inside" + " "
              + "Resource{" + resource + "}."
              + (received != null ? "" : " " + "To indicate failure return a null Resource "
              + "object, rather than a Resource object containing null data."));
          onLoadFailed(exception);
          return;
        }
    
        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);
      }
    

    完成之后进行资源释放,并修改资源状态等 ,这里不做详尽的解释(太多);ok 继续回来看请求逻辑

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

    glide的请求在onSizeReady中:

    @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;
    
        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并且传入一堆参数,主要是各种属性的线程池,内存状态,OPtion等;那么继续看加载的实质代码:

    public <R> LoadStatus load(
          .....参数省略) {
          
        ......
    
        EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
        if (active != null) {
          cb.onResourceReady(active, DataSource.MEMORY_CACHE);
          if (Log.isLoggable(TAG, Log.VERBOSE)) {
            logWithTimeAndKey("Loaded resource from active resources", startTime, key);
          }
          return null;
        }
    
        EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
        if (cached != null) {
          cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
          if (Log.isLoggable(TAG, Log.VERBOSE)) {
            logWithTimeAndKey("Loaded resource from cache", startTime, key);
          }
          return null;
        }
    
        EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
        if (current != null) {
          current.addCallback(cb);
          if (Log.isLoggable(TAG, Log.VERBOSE)) {
            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);
    
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
          logWithTimeAndKey("Started new load", startTime, key);
        }
        return new LoadStatus(cb, engineJob);
      }
    

    OMG 代码好长;首先看加扎起过程Glide并不会直接加载他是有两次缓存的:LruCash和ActiveCash;在Glide中当加载完毕,首先会将图片短时间从LruCash中取出来放入ActiveCash,进行临时存储;所以首先从ActiveCash中获取图片

     EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    

    接着是从LruCash中获取图片:

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

    最后才进行加载:url:

     engineJob.addCallback(cb);
     engineJob.start(decodeJob);
    

    注意Glide会有会调来监听加载图片的每一个阶段;比如我们在开发中会有这样的场景:

         SimpleTarget<Drawable> into = GlideApp.with(this)
                    .load(url)
                    .placeholder(R.mipmap.ic_launcher_round)
                    //开始请求
                    .into(new SimpleTarget<Drawable>() {
                        @Override
                        public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                            Log.i("glide_life", "onResourceReady");
                            mIv.setImageDrawable(resource);
                        }
    
                        @Override
                        public void setRequest(@Nullable Request request) {
                            super.setRequest(request);
                            Log.i("glide_life", "setRequest");
    
                        }
    
                         .....省略一些方法
                    });
    

    ok 继续回归网络加载 engineJob.start(decodeJob);

     public void start(DecodeJob<R> decodeJob) {
        this.decodeJob = decodeJob;
        GlideExecutor executor = decodeJob.willDecodeFromCache()
            ? diskCacheExecutor
            : getActiveSourceExecutor();
        executor.execute(decodeJob);
      }
    

    由上面代码 继续看GlideExecutor下execute:

      public void execute(Runnable command) {
            if (command == null)
                throw new NullPointerException();
            int c = ctl.get();
            if (workerCountOf(c) < corePoolSize) {
                if (addWorker(command, true))
                    return;
                c = ctl.get();
            }
            if (isRunning(c) && workQueue.offer(command)) {
                int recheck = ctl.get();
                if (! isRunning(recheck) && remove(command))
                    reject(command);
                else if (workerCountOf(recheck) == 0)
                    addWorker(null, false);
            }
            else if (!addWorker(command, false))
                reject(command);
        }
    

    what? 为什么传的是DecodeJob回来的是Runable,而且execute明显是一些资源收尾的工作;好吧 DecodeJob 实现了Runable,并且在run方法中实现网络请求:

    @Override
      public void run() {
        DataFetcher<?> localFetcher = currentFetcher;
        try {
          if (isCancelled) {
            notifyFailed();
            return;
          }
          runWrapped();
        } catch (Throwable t) {
          if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "DecodeJob threw unexpectedly"
                + ", isCancelled: " + isCancelled
                + ", stage: " + stage, t);
          }
          if (stage != Stage.ENCODE) {
            throwables.add(t);
            notifyFailed();
          }
          if (!isCancelled) {
            throw t;
          }
        } finally {
          // Keeping track of the fetcher here and calling cleanup is excessively paranoid, we call
          // close in all cases anyway.
          if (localFetcher != null) {
            localFetcher.cleanup();
          }
          TraceCompat.endSection();
        }
      }
    

    在这里同样通过状态进行请求;当上请求cancle已经cancel则 notifyFailed()(注意glide是可以取消网络加载的),否则通过请求runWrapped()来请求网络;

     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);
        }
      }
    
    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:
            // Skip loading from source if the user opted to only retrieve the resource from cache.
            return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
          case SOURCE:
          case FINISHED:
            return Stage.FINISHED;
          default:
            throw new IllegalArgumentException("Unrecognized stage: " + current);
        }
      }
    

    首先是获取加载状态,然后在getNextGenerator()获取图片加载器;

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

    在Glide中有3种加载器(暂时这样定义)DataCacheGenerator,SourceGenerator,ResourceCacheGenerator
    基于以上3钟然后在runGenerators()中进行真正的加载:currentGenerator.startNext()
    下面以SourceGenerator为例

      @Override
      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;
      }
    

    核心加载逻辑: loadData.fetcher.loadData(helper.getPriority(), this);

    尽可能详尽的对glide 就行剖析.重点是思想.希望对大家有所助益

    相关文章

      网友评论

          本文标题:Glide 源码解析 ----- android source

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