Glide源码解析4 -- Glide源码总纲

一 源码分析

根据前面即便,想来对Glide源码已经有了初步了解,这篇是最后篇,主要对前面几篇的源码进行总结,从Glide的流式调用来分析:

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

1.1 with()

这个方法传入的是上下文context,主要是创建Clide对象和将Glide与传入的context进行生命周期的绑定

1.1.1 重要对象名

在这里插入图片描述

1.1.2 具体源码

Glide.java

public class Glide {
    ...

    // with()重载种类非常多,根据传入的参数可分为:
    // 1. 非Application类型的参数(Activity & Fragment  )
    // 2. Application类型的参数(Context)
    // 下面将详细分析

// 参数1:Application类型
 public static RequestManager with(Context context) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        // 步骤1:调用RequestManagerRetriever类的静态get()获得RequestManagerRetriever对象 - 单例实现
        return retriever.get(context);
        // 步骤2:调用RequestManagerRetriever实例的get()获取RequestManager对象 & 绑定图片加载的生命周期 ->>分析1
    }

// 参数2:非Application类型(Activity & Fragment )
    public static RequestManager with(Activity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(activity);
    }

    public static RequestManager with(Fragment fragment) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(fragment);

  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static RequestManager with(android.app.Fragment fragment) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(fragment);
    }

    }
}

RequestManagerRetriever.java

```java
 public class RequestManagerRetriever implements Handler.Callback {
      ...

    // 实例的get()重载种类很多,参数分为:(与with()类似)
    // 1. Application类型(Context)
    // 2. 非Application类型(Activity & Fragment )- >>分析3
    // 下面会详细分析

// 参数1:Application类型(Context) 
   public RequestManager get(Context context) {
        // 调用getApplicationManager()最终获取一个RequestManager对象 
        // 因为Application对象的生命周期即App的生命周期
        // 所以Glide加载图片的生命周期是自动与应用程序的生命周期绑定,不需要做特殊处理(若应用程序关闭,Glide的加载也会终止)
        return getApplicationManager(context);

    }

// 参数2:非Application类型(Activity & Fragment  )
// 将Glide加载图片的生命周期与Activity生命周期同步的具体做法:向当前的Activity添加一个隐藏的Fragment
// 原因:因Fragment的生命周期 与 Activity 的是同步的,通过添加隐藏的Fragment 从而监听Activity的生命周期,从而实现Glide加载图片的生命周期与Activity的生命周期 进行同步。
 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public RequestManager get(Activity activity) {
        if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            return get(activity.getApplicationContext()); 
        } else {
   			 //判断activity是否已经销毁
            assertNotDestroyed(activity);
      		 // 获取FragmentManager 对象
            android.app.FragmentManager fm = activity.getFragmentManager();
         	// 通过fragmentGet返回RequestManager
            return fragmentGet(activity, fm);  // 分析 1
        }
    }

    public RequestManager get(FragmentActivity activity) {
    }

    public RequestManager get(Fragment fragment) {
    }

}


分析1// 作用:
           // 1. 创建Fragment
           // 2. 向当前的Activity中添加一个隐藏的Fragment
           // 3. 将RequestManager与该隐藏的Fragment进行绑定
 RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
     
        RequestManagerFragment current = getRequestManagerFragment(fm);
        // 获取RequestManagerFragment
        // 作用:利用Fragment进行请求的生命周期管理 

        RequestManager requestManager = current.getRequestManager();

        // 若requestManager 为空,即首次加载初始化requestManager 
        if (requestManager == null) {
            // 创建RequestManager传入Lifecycle实现类,如ActivityFragmentLifecycle
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);
            // 调用setRequestManager设置到RequestManagerFragment 
        }
        return requestManager;
    }



private RequestManager getApplicationManager(Context context) {
      ...
        Glide glide = Glide.get(context);  // 分析2
        // 通过单例模式创建Glide实例
        applicationManager =
            new RequestManager(
                glide, new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
      }
    }
  }
  return applicationManager;
}

  分析 2  **Glide.java**


public static Glide get(Context context) {
  if (glide == null) {
  // 单例模式
    synchronized (Glide.class) {
      if (glide == null) {
        Context applicationContext = context.getApplicationContext();
        // 解析清单文件配置的自定义GlideModule的metadata标签,返回一个GlideModule集合
        List<GlideModule> modules = new ManifestParser(applicationContext).parse();
		// 步骤1:创建GlideBuilder对象
        GlideBuilder builder = new GlideBuilder(applicationContext);   
        for (GlideModule module : modules) {
          module.applyOptions(applicationContext, builder);
        }
        // 步骤2:根据GlideBuilder对象创建Glide实例
        // GlideBuilder会为Glide设置一默认配置,如:Engine,RequestOptions,GlideExecutor,MemorySizeCalculator
        glide = builder.createGlide();
        for (GlideModule module : modules) {
          // 步骤3:利用GlideModule 进行延迟性的配置和ModelLoaders的注册
          module.registerComponents(applicationContext, glide.registry);
         
        }
      }
    }
  }
  return glide;
}

1.1.3 总结

with()方法是为了得到RequestManager对象,而这个对象主要是用来管理Glide请求与上下文的生命周期绑定的,具体生命周期如何绑定,请点击Glide生命周期解析

1.2 load()

此时通过with()方法之后,返回了RequestManager,所以第二部load()其实就是RequestManager的load()方法。

1.2.1 作用

预先创建好对图片的一系列操作(加载,编解码,转码)的对象,并且把这些全部封装到DrawableTypeRequest对象中。
Glide支持的图片加载方式有URL,图片本地路径,资源ID等,因为RequestManager类肯定存在load()的多个重载方法,这里我们就只分析最常见的URL字符串的加载方式,即load(String url)

1.2.2 具体源码

RequestManager.java

public class RequestManager implements LifecycleListener {

    // 仅贴出关键代码
    ...

     public DrawableTypeRequest<String> load(String string) {
         // 先调用fromString()再调用load()
        // load()作用:传入图片URL地址
       // fromString()作用 ->>分析1
        return (DrawableTypeRequest<String>) fromString().load(string);
    }

分析1:fromString()
    public DrawableTypeRequest<String> fromString() {
    // loadGeneric()的作用 ->>分析2
        return loadGeneric(String.class);       
    }

分析2:loadGeneric()
    private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
      /* 创建第1个ModelLoader对象;作用:加载图片
        Glide会根据load()方法传入不同类型参数,得到不同的ModelLoader对象
       此处传入参数是String.class,因此得到的是StreamStringLoader对象(实现了ModelLoader接口)*/
        ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);
          /* 创建第2个ModelLoader对象,作用同上:加载图片
         此处得到的是FileDescriptorModelLoader对象*/
        ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader = Glide.buildFileDescriptorModelLoader(modelClass, context);

   /*创建DrawableTypeRequest对象 & 传入刚才创建的ModelLoader对象 和 其他初始化配置的参数*/    
        return optionsApplier.apply(
                new DrawableTypeRequest<T>    (modelClass, streamModelLoader, fileDescriptorModelLoader, context,
                        glide, requestTracker, lifecycle, optionsApplier)); //分析3
}









分析3DrawableTypeRequest.java
// 关注1:构造方法
public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {

//通过构造函数将前面创建的对象依次初始化封装到DrawableTypeRequest
  DrawableTypeRequest(Class<ModelType> modelClass, ModelLoader<ModelType, InputStream> streamModelLoader,
        ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide,
        RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
    super(context, modelClass,
    //前面创建的两个modelLoader传入了buildProvider(),分析4
            buildProvider(glide, streamModelLoader,  fileDescriptorModelLoader, GifBitmapWrapper.class,
                    GlideDrawable.class, null),
            glide, requestTracker, lifecycle);


//DrawableTypeRequest的方法之一:强制加载静态图片
    public BitmapTypeRequest<ModelType> asBitmap() {
        return optionsApplier.apply(new BitmapTypeRequest<ModelType>(this, streamModelLoader,
                fileDescriptorModelLoader, optionsApplier));
        // 创建BitmapTypeRequest对象
    }

    // asGif() 作用:强制加载 动态图片
    public GifTypeRequest<ModelType> asGif() {
        return optionsApplier.apply(new GifTypeRequest<ModelType>(this, streamModelLoader, optionsApplier));
        // 创建GifTypeRequest对象

        // 注:若没指定,则默认使用DrawableTypeRequest
    }

}



分析4buildProvider()
private static <A, Z, R> FixedLoadProvider<A, ImageVideoWrapper, Z, R> buildProvider(Glide glide,
            ModelLoader<A, InputStream> streamModelLoader,
            ModelLoader<A, ParcelFileDescriptor> fileDescriptorModelLoader, Class<Z> resourceClass,
            Class<R> transcodedClass,
            ResourceTranscoder<Z, R> transcoder) {

        if (transcoder == null) {
                    // 创建GifBitmapWrapperDrawableTranscoder对象(实现了ResourceTranscoder接口)
            // 作用:对图片进行转码
            transcoder = glide.buildTranscoder(resourceClass, transcodedClass);
        }
// 创建ImageVideoGifDrawableLoadProvider对象(实现了DataLoadProvider接口)
        // 作用:对图片进行编解码 
        DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class,
                resourceClass);
        
        // 创建ImageVideoModelLoader
        // 并把上面创建的两个ModelLoader:streamModelLoader和fileDescriptorModelLoader封装到了ImageVideoModelLoader中
        ImageVideoModelLoader<A> modelLoader = new ImageVideoModelLoader<A>(streamModelLoader,
                fileDescriptorModelLoader);

       // 创建FixedLoadProvider对象
       // 把上面创建的GifBitmapWrapperDrawableTranscoder、ImageVideoModelLoader、ImageVideoGifDrawableLoadProvider都封装进去
      // 注:FixedLoadProvider对象就是第3步into()中onSizeReady()的loadProvider对象
        return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);

    }

在RequestManager的load()中,通过fromString()最终返回了一个DrawableTypeRequest对象,随后调用DrawableTypeRequest的into()方法,回看分析1,但是翻看DrawableTypeRequest源码,并没有load()方法和into()方法,这两个方法其实在它的父类里,我们来看看它们的继承关系:
在这里插入图片描述


public class DrawableRequestBuilder<ModelType>
        extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
        implements BitmapOptions, DrawableOptions {

        ... 
        // 最终load()方法返回的其实就是一个DrawableRequestBuilder对象
  @Override
    public DrawableRequestBuilder<ModelType> load(ModelType model) {
        super.load(model);
        return this;
    }

// 特别注意:DrawableRequestBuilder类中有很多使用Glide的API方法,此处不做过多描述
@Override
    public Target<GlideDrawable> into(ImageView view) {
        return super.into(view);
    }



}

1.2.3 总结

load()中预先创建好对图片进行一系列操作(加载、编解码、转码)的对象,并全部封装到 DrawableTypeRequest对象中
在这里插入图片描述
在这里插入图片描述

1.3 into()

1.3.1 作用

前面我们通过RequestManager的load()方法将加载图片需要的参数都封装进了DrawableTypeRequest对象进而调用其into()方法,此时这个方法只要就负责构建Request(Glide源码解析1 – Request的创建)和网络请求了

1.3.2 逻辑图

在这里插入图片描述

1.3.3 具体代码

前面已经说过,into()方法其实调用的是DrawableTypeRequest的父类DrawableRequestBuilder的load()方法,我们来看一下这个方法:

**DrawableRequestBuilder.java**

public class DrawableRequestBuilder<ModelType>
        extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
        implements BitmapOptions, DrawableOptions {
        
 // 调用DrawableRequestBuilder的父类GenericRequestBuilder的into() ->>分析1
 @Override
    public Target<GlideDrawable> into(ImageView view) {
        return super.into(view);
 
    }
}









分析1GenericRequestBuilder.java


public class GenericRequestBuilder<ModelType> {

  ...

  public Target<TranscodeType> into(ImageView view) {

  // 判断是否在主线程(跟新UI只能在主线程)
  // 此处逻辑先不讲解,后面会详细说明,直接跳到方法的最后一行
    Util.assertMainThread();
    if (view == null) {
        throw new IllegalArgumentException("You must pass in a non null View");
    }
    if (!isTransformationSet && view.getScaleType() != null) {
        switch (view.getScaleType()) {
            case CENTER_CROP:
                applyCenterCrop();
                break;
            case FIT_CENTER:
            case FIT_START:
            case FIT_END:
                applyFitCenter();
                break;
            //$CASES-OMITTED$
            default:
                // Do nothing.
        }
    }
      // 创建Target对象:用于最终展示图片 ->>分析2
    // 从分析3回来
    return into(glide.buildImageViewTarget(view, transcodeClass));
 
  }
}

		



分析2:buildImageViewTarget.java

<R> Target<R> buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
    // ->>分析3

}




分析3ImageViewTargetFactory.java

public class ImageViewTargetFactory {

    public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {


        // 根据传入的class参数构建不同的Target对象,分为三种情况:
        // 情况1:若加载图片时调用了asBitmap(),那么构建的是BitmapImageViewTarget对象
       // 情况2:否则构建的是GlideDrawableImageViewTarget对象
       // 情况3:DrawableImageViewTarget对象基本用不到,此处忽略
       // 具体请看以下代码
        if (GlideDrawable.class.isAssignableFrom(clazz)) {
            return (Target<Z>) new GlideDrawableImageViewTarget(view);
        } else 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)");
        }
    }
}


在这里插入图片描述
这里主要将装载图片的VIew(ImageView)进行封装,大部分会封装成GlideDrawableImageViewTarget对象,最终作为参数传入GenericRequestBuilder的into()方法里(分析1)

**GenericRequestBuilder,java**

public <Y extends Target<TranscodeType>> Y into(Y target) {
	// 关注1:构建Request对象:发出加载图片请求
    Request request = buildRequest(target);    分析1
     // 将请求设置到target
    target.setRequest(request);
   	// 将target加入到lifecycle
    lifecycle.addListener(target);
    // 关注2:执行网络请求Request
    requestTracker.runRequest(request);  分析2
    return target;

}

分析1**构建Request对象:**

    private Request buildRequest(Target<TranscodeType> target) {
        if (priority == null) {
            priority = Priority.NORMAL;
        }
        return buildRequestRecursive(target, null);  分析2
    }
    private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) {
        // 90%的代码用于处理缩略图,此处仅关注主流程,即如何构建Request对象
        // 仅贴出关键代码(如何构建Request对象)  
        ... 

        ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
        Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
        // 往下调用
        }
private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority,
        RequestCoordinator requestCoordinator) {
    // 调用了GenericRequest的obtain()
    // 作用:将在load()中调用的所有API参数都组装到Request对象当中 
    return GenericRequest.obtain(
            loadProvider,
            model,
            signature,
            context,
            priority,
            target,
            sizeMultiplier,
            placeholderDrawable,
            placeholderId,
            errorPlaceholder,
            errorId,
            fallbackDrawable,
            fallbackResource,
            requestListener,
            requestCoordinator,
            glide.getEngine(),
            transformation,
            transcodeClass,
            isCacheable,
            animationFactory,
            overrideWidth,
            overrideHeight,
            diskCacheStrategy);

}


public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback,
        ResourceCallback {
    // 仅贴出关键代码
    ...

    public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(
            LoadProvider<A, T, Z, R> loadProvider,
            A model,
            Key signature,
            Context context,
            Priority priority,
            Target<R> target,
            float sizeMultiplier,
            Drawable placeholderDrawable,
            int placeholderResourceId,
            Drawable errorDrawable,
            int errorResourceId,
            Drawable fallbackDrawable,
            int fallbackResourceId,
            RequestListener<? super A, R> requestListener,
            RequestCoordinator requestCoordinator,
            Engine engine,
            Transformation<Z> transformation,
            Class<R> transcodeClass,
            boolean isMemoryCacheable,
            GlideAnimationFactory<R> animationFactory,
            int overrideWidth,
            int overrideHeight,
            DiskCacheStrategy diskCacheStrategy) {
        @SuppressWarnings("unchecked")
        GenericRequest<A, T, Z, R> request = (GenericRequest<A, T, Z, R>) REQUEST_POOL.poll();
        if (request == null) {
            request = new GenericRequest<A, T, Z, R>();
            // 创建GenericRequest对象
        }
        // init()作用:将传入的Load()中的API参数赋值到GenericRequest的成员变量
        request.init(loadProvider,
                model,
                signature,
                context,
                priority,
                target,
                sizeMultiplier,
                placeholderDrawable,
                placeholderResourceId,
                errorDrawable,
                errorResourceId,
                fallbackDrawable,
                fallbackResourceId,
                requestListener,
                requestCoordinator,
                engine,
                transformation,
                transcodeClass,
                isMemoryCacheable,
                animationFactory,
                overrideWidth,
                overrideHeight,
                diskCacheStrategy);
        return request;
        // 返回GenericRequest对象
    }

    ...
}

到这里Request对象创建完毕
在这里插入图片描述

执行网络请求:requestTracker.runRequest(request);(分析2)


**requestTracker.java**

public void runRequest(Request request) {
    // 此时的Request是GenericRequest对象
    requests.add(request);
    // 将每个提交的请求加入到一个set中:管理请求
    
    // 判断Glide当前是否处于暂停状态    
    if (!isPaused) {
        // 若不处于暂停状态,则调用GenericRequest的begin()来执行Request
        request.begin(); //关注1
    } else {
        // 若处于暂停,则先将Request添加到待执行队列里面,等暂停状态解除后再执行
        pendingRequests.add(request);
    }
}


关注1GenericRequest.begin()
   public void begin() {
        startTime = LogTime.getLogTime();
        //model可以看做是URL
        if (model == null) {
            onException(null); //分析1
            return;
        }

        status = Status.WAITING_FOR_SIZE;
        // 图片加载情况分两种:
		// 1. Glide可以通过override()来制定宽高
		// 2. 无使用
        
       // 情况1:使用了override() API为图片指定了一个固定的宽高
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
            onSizeReady(overrideWidth, overrideHeight); //分析2
        } else {
            target.getSize(this);
        }
		//情况2: target.onLoadStarted()
        if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
        // target.onLoadStarted()的内部会根据ImageView的layout_width和layout_height值做一系列的计算,来算出图片显示的宽高
        // 计算后,也会调用onSizeReady()方法进行加载
            target.onLoadStarted(getPlaceholderDrawable());
        }
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            logV("finished run method in " + LogTime.getElapsedMillis(startTime));
        }
    }





分析1:若model=null,也就是URL,就会调用onException(),内部调用了setErrorPlaceholder()

private void setErrorPlaceholder(Exception e) {

    Drawable error = model == null ? getFallbackDrawable() : null;

    // 若有error的占位图,则采用先获取error的占位图
    if (error == null) {
      error = getErrorDrawable();
    }
    // 若没有error的占位图,则再去获取一个loading占位图
    if (error == null) {
        error = getPlaceholderDrawable();
    }
    target.onLoadFailed(e, error);
    // 将占位图(error / loading)传入到onLoadFailed()中 
}


**ImageViewTarget.java**
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z> implements GlideAnimation.ViewAdapter {
    ...

    @Override
    public void onLoadFailed(Exception e, Drawable errorDrawable) {
        view.setImageDrawable(errorDrawable);
        // 将该error占位图显示到ImageView
    }

    @Override
    public void onLoadStarted(Drawable placeholder) {
        view.setImageDrawable(placeholder);
        // 在图片请求开始前,会先使用Loading占位图代替最终的图片显示
        // 在begin()时调用(回看分析7)
    }
**看到这里就明白了我们常用到的占位图和error图在哪里被设置了吧!!**





分析2onSizeReady()
public void onSizeReady(int width, int height) {

    // loadProvider 对象 即 第2步load()中的FixedLoadProvider对象 
    // 里面封装了GifBitmapWrapperDrawableTranscoder、ImageVideoModelLoader、ImageVideoGifDrawableLoadProvider对象)
    // ->>请回看第2步load()中的DrawableTypeRequest类

	// 从loadProvider 对象中获取ImageVideoModelLoader对象
    ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
     // 从loadProvider 对象中获取GifBitmapWrapperDrawableTranscoder对象
    ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
   

 // 创建ImageVideoFetcher对象(传入HttpUrlFetcher对象)
    final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);
    // ->>分析3
   
   
      // 将上述获得的ImageVideoFetcher、GifBitmapWrapperDrawableTranscoder等一起传入到了Engine的load()方法中 ->>分析4
    loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
            priority, isMemoryCacheable, diskCacheStrategy, this);


    }
    ...
}




分析3ImageVideoModelLoader.getResourceFetcher()

public class ImageVideoModelLoader<A> implements ModelLoader<A, ImageVideoWrapper> {
  
    @Override
    public DataFetcher<ImageVideoWrapper> getResourceFetcher(A model, int width, int height) {
        
         DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher = null;
         if (fileDescriptorLoader != null) {
             // fileDescriptorLoader是在第2步load()中创建的FileDescriptorModelLoader:用于加载图片
           // 调用FileDescriptorModelLoader的getResourceFetcher()会得到一个HttpUrlFetcher对象
            fileDescriptorFetcher = fileDescriptorLoader.getResourceFetcher(model, width, height);
        
        }

        DataFetcher<InputStream> streamFetcher = null;
        if (streamLoader != null) {
               // streamLoader是在第2步load()中创建的StreamStringLoader:用于加载图片
           // 调用streamLoader的getResourceFetcher()会得到一个HttpUrlFetcher对象
            streamFetcher = streamLoader.getResourceFetcher(model, width, height);
     
        }
      

        if (streamFetcher != null || fileDescriptorFetcher != null) {
                // 创建ImageVideoFetcher对象,并把上述获得的2个HttpUrlFetcher对象传进去
        // 即调用ImageVideoModelLoader的getResourceFetcher()得到的是ImageVideoFetcher
            return new ImageVideoFetcher(streamFetcher, fileDescriptorFetcher);

        } else {
            return null;
        }
    }
}



分析4Engine.load()

public class Engine implements EngineJobListener,
        MemoryCache.ResourceRemovedListener,
        EngineResource.ResourceListener {

      ...
  

        EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);

		...这里省略了代码,主要是Glide的内存缓存,具体可以去看Glide源码解析3--内存缓存

        // 创建EngineJob对象
        // 作用:开启线程(作异步加载图片)

        DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
                transcoder, diskCacheProvider, diskCacheStrategy, priority);
        // 创建DecodeJob对象
        // 作用:对图片解码(较复杂,下面会详细说明)

        EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
        // 创建EngineRunnable对象
        jobs.put(key, engineJob);
        engineJob.addCallback(cb);
              // 执行EngineRunnable对象
        // 即在子线程中执行EngineRunnable的run()方法 ->>分析5
        engineJob.start(runnable);
  
         return new LoadStatus(cb, engineJob);
    }

    ...
}



分析5EngineRunnable.java
   @Override
    public void run() {
   
    try {
     // 调用decode() 并 返回了一个Resource对象 ->>分析6
        resource = decode();
       

    } catch (Exception e) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Exception decoding", e);
        }
       ...
}



private Resource<?> decode() throws Exception {

// 分两种情况:从缓存当中读(解码)图片 & 不从缓存中读(解码)图片

    if (isDecodingFromCache()) {
    // 若从缓存中decode图片:执行decodeFromCache()
    // 本文先不讨论缓存情况,具体可以看Glide源码解析3 -- 内存缓存
        return decodeFromCache();
    } else {
        // 不从缓存中读(解码)图片:执行decodeFromSource()  ->>分析 7 
        return decodeFromSource();
    }
}


分析7decodeFromSource()  
private Resource<?> decodeFromSource() throws Exception {
    return decodeJob.decodeFromSource();
    // 调用了DecodeJob的decodeFromSource()方法 ->>分析8
}


分析8DecodeJob.decodeFromSource() 
class DecodeJob<A, T, Z> {
    ...

   public Resource<Z> decodeFromSource() throws Exception {
        Resource<T> decoded = decodeSource();
        // 获得Resource对象 ->>分析9
        return transformEncodeAndTranscode(decoded);
        // 调用transformEncodeAndTranscode()方法来处理该Resource对象。
    }




分析9decodeSource() 

    private Resource<T> decodeSource() throws Exception {
    ...

        try {
            final A data = fetcher.loadData(priority);
            // 该fetcher是在分析2:onSizeReady()中得到的ImageVideoFetcher对象
            // 即调用ImageVideoFetcher的loadData() - >>分析10

            // 从分析12回来时看这里:
            decoded = decodeFromSourceData(data);
            // 将分析12创建的ImageVideoWrapper对象传入到decodeFromSourceData(),解码该对象 -->分析13

      }

    ...
}




分析10: fetcher.loadData()  
@Override
public ImageVideoWrapper loadData(Priority priority) throws Exception {
    InputStream is = null;

    if (streamFetcher != null) {
        try {
              // 该streamFetcher是创建ImageVideoFetcher对象时传入的HttpUrlFetcher
          // 因此这里调用的是HttpUrlFetcher的loadData() ->>分析12
            is = streamFetcher.loadData(priority);
     
        } catch (Exception e) {

    return new ImageVideoWrapper(is, fileDescriptor);
}






分析12HttpUrlFetcher.loadData()


// 此处是网络请求的代码
public class HttpUrlFetcher implements DataFetcher<InputStream> {

    @Override
    public InputStream loadData(Priority priority) throws Exception {
        return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
        // 继续往下看
    }

    private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers)
           ...

        // 静态工厂模式创建HttpURLConnection对象
        urlConnection = connectionFactory.build(url);
        for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
          urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
        }
        //设置请求参数
        //设置连接超时时间2500ms
        urlConnection.setConnectTimeout(2500);
        //设置读取超时时间2500ms
        urlConnection.setReadTimeout(2500);
        //不使用http缓存
        urlConnection.setUseCaches(false);
        urlConnection.setDoInput(true);

        // Connect explicitly to avoid errors in decoders if connection fails.
        urlConnection.connect();
        if (isCancelled) {
            return null;
        }
        final int statusCode = urlConnection.getResponseCode();
        if (statusCode / 100 == 2) {
              //请求成功
            return getStreamForSuccessfulRequest(urlConnection);
            // 继续往下看
        } 
    }

      private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection)
            throws IOException {
        if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
            int contentLength = urlConnection.getContentLength();
            stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);
        } else {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "Got non empty content encoding: " + urlConnection.getContentEncoding());
            }
            stream = urlConnection.getInputStream();
        }
        return stream;
        // 最终返回InputStream对象(但还没开始读取数据),回到分析9
    }
        
    }
}



我们回到分析9,继续看decodeFromSourceData()方法:

分析13decodeFromSourceData()

 // 将分析12创建的ImageVideoWrapper对象传入到decodeFromSourceData(),解码该对象

private Resource<T> decodeFromSourceData(A data) throws IOException {

        decoded = loadProvider.getSourceDecoder().decode(data, width, height);
        // 调用loadProvider.getSourceDecoder()得到的是GifBitmapWrapperResourceDecoder对象
        // 即调用GifBitmapWrapperResourceDecoder对象的decode()来对图片进行解码 ->>分析14
    
    return decoded;
}



分析14GifBitmapWrapperResourceDecoder.decode()
    public class GifBitmapWrapperResourceDecoder implements ResourceDecoder<ImageVideoWrapper, GifBitmapWrapper> {

    ...

    @Override
    public Resource<GifBitmapWrapper> decode(ImageVideoWrapper source, int width, int height) throws IOException {

            wrapper = decode(source, width, height, tempBytes);
            // 传入参数,并调用了另外一个decode()进行重载 ->>分析15

    }


分析15decode()
 private GifBitmapWrapper decode(ImageVideoWrapper source, int width, int height, byte[] bytes) throws IOException {
        final GifBitmapWrapper result;
        if (source.getStream() != null) {
            result = decodeStream(source, width, height, bytes);
            // 作用:从服务器返回的流当中读取数据- >>分析16
            
        } else {
            result = decodeBitmapWrapper(source, width, height);
        }
        return result;
    }



分析16:decodeStream()

// 作用:从服务器返回的流当中读取数据
// 读取方式:
        // 1. 从流中读取2个字节的数据:判断该图是GIF图还是普通的静图
        // 2. 若是GIF图,就调用decodeGifWrapper() 解码
        // 3. 若普通静图,就调用decodeBitmapWrapper() 解码
        // 此处仅分析 对于静图解码
    private GifBitmapWrapper decodeStream(ImageVideoWrapper source, int width, int height, byte[] bytes)
            throws IOException {
        
        // 步骤1:从流中读取两个2字节数据进行图片类型的判断
        InputStream bis = streamFactory.build(source.getStream(), bytes);
        bis.mark(MARK_LIMIT_BYTES);
        ImageHeaderParser.ImageType type = parser.parse(bis);
        bis.reset();
        GifBitmapWrapper result = null;

        // 步骤2:若是GIF图,就调用decodeGifWrapper() 解码
        if (type == ImageHeaderParser.ImageType.GIF) {
            result = decodeGifWrapper(bis, width, height);
        }

        // 步骤3:若是普通静图,就调用decodeBitmapWrapper()解码
        if (result == null) {
            ImageVideoWrapper forBitmapDecoder = new ImageVideoWrapper(bis, source.getFileDescriptor());
            result = decodeBitmapWrapper(forBitmapDecoder, width, height);
         
        }
        return result;
    }

就分析到这里,下面的代码太过于复杂,我们主要知道下面是对静图和动图的解码,解码后封装到GifBitmapWrapper(既能封装GIF,又能封装Bitmap)

我们回到分析5:EngineRunnable的run()

@Override
public void run() {

    try {
        resource = decode();
        // 最终得到了Resource<GlideDrawable>对象
        // 接下来的工作:将该图片显示出来

    } catch (Exception e) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Exception decoding", e);
        }
        exception = e;
    }
    if (isCancelled) {
        if (resource != null) {
            resource.recycle();
        }
        return;
    }
    if (resource == null) {
        onLoadFailed(exception);
    } else {
        onLoadComplete(resource);
        // 表示图片加载已经完成 ->>分析17
    }
}





分析17onLoadComplete()

这里就是在主线程显示图片了:


private void onLoadComplete(Resource resource) {
    manager.onResourceReady(resource);
    // 该manager即EngineJob对象
    // 实际上调用的是EngineJob的onResourceReady() - >>分析18
}



分析18onResourceReady()
class EngineJob implements EngineRunnable.EngineRunnableManager {
    ...

    private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new MainThreadCallback());
    // 创建线程,并绑定主线程的Looper
    private final List<ResourceCallback> cbs = new ArrayList<ResourceCallback>();

    @Override
    public void onResourceReady(final Resource<?> resource) {
        this.resource = resource;
        MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
       // 使用Handler发出一条 MSG_COMPLETE 消息
      // 那么在MainThreadCallback的handleMessage()方法中就会收到这条消息 ->>分析19
      // 从此处开始,所有逻辑又回到主线程中进行了,即更新UI

    }


分析19private static class MainThreadCallback implements Handler.Callback {

        @Override
        public boolean handleMessage(Message message) {
            if (MSG_COMPLETE == message.what || MSG_EXCEPTION == message.what) {
                EngineJob job = (EngineJob) message.obj;
                if (MSG_COMPLETE == message.what) {
                    job.handleResultOnMainThread();
                    // 调用 EngineJob的handleResultOnMainThread() ->>分析20
                } else {
                    job.handleExceptionOnMainThread();
                }
                return true;
            }
            return false;
        }
    }
    ...
}


分析20handleResultOnMainThread()
private void handleResultOnMainThread() {

        // 通过循环,调用了所有ResourceCallback的onResourceReady()
        for (ResourceCallback cb : cbs) {
            if (!isInIgnoredCallbacks(cb)) {
                engineResource.acquire(); //在缓存篇里提及过,acquire主要是acquire+1,表明图片正在使用
                  // ResourceCallback 是在Engine的load()方法当中添加的->>分析21
                cb.onResourceReady(engineResource);  分析22
              
            }
        }
        engineResource.release();
    }



分析21Engine.load()



public class Engine implements EngineJobListener,
        MemoryCache.ResourceRemovedListener,
        EngineResource.ResourceListener {

      ...

      public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
            DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder, Priority priority, 
            boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {

              engineJob.addCallback(cb);
           // 调用addCallback()注册了一个ResourceCallback
           // 上述参数cb是load()传入的的最后一个参数
            // 而load()是在GenericRequest的onSizeReady()调用的
        return new LoadStatus(cb, engineJob);
    }

    ...
}

public void onSizeReady(int width, int height) {

... 
    loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
            priority, isMemoryCacheable, diskCacheStrategy, this);
            // load()最后一个参数是this
            // 所以,ResourceCallback类型参数cb是this
            // 而GenericRequest本身实现了ResourceCallback接口
            // 因此,EngineJob的回调 = cb.onResourceReady(engineResource) = 最终回调GenericRequest的onResourceReady() 

    }
}



分析22GenericRequestonResourceReady()
// 重载1
public void onResourceReady(Resource<?> resource) {
    Object received = resource.get();
    // 获取封装的图片对象(GlideBitmapDrawable对象 或 GifDrawable对象

       onResourceReady(resource, (R) received);
      // 然后将该获得的图片对象传入到了onResourceReady()的重载方法中 ->>看重载2
}


// 重载2
private void onResourceReady(Resource<?> resource, R result) {
    
        ...

        target.onResourceReady(result, animation);
        // Target是在第3步into()的最后1行调用glide.buildImageViewTarget()方法来构建出的Target:GlideDrawableImageViewTarget对象
        // ->>分析23

    }


分析23GlideDrawableImageViewTarget.onResourceReady()
public class GlideDrawableImageViewTarget extends ImageViewTarget<GlideDrawable> {

    @Override
    public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
        if (!resource.isAnimated()) {
            float viewRatio = view.getWidth() / (float) view.getHeight();
            float drawableRatio = resource.getIntrinsicWidth() / (float) resource.getIntrinsicHeight();
            if (Math.abs(viewRatio - 1f) <= SQUARE_RATIO_MARGIN
                    && Math.abs(drawableRatio - 1f) <= SQUARE_RATIO_MARGIN) {
                resource = new SquaringDrawable(resource, view.getWidth());
            }
        }
        super.onResourceReady(resource, animation);
        // 若是静态图片,就调用父类的.onResourceReady() 将GlideDrawable显示到ImageView上
        // GlideDrawableImageViewTarget的父类是ImageViewTarget ->>分析24
        this.resource = resource;
        resource.setLoopCount(maxLoopCount);
        resource.start();
        // 如果是GIF图片,就调用resource.start()方法开始播放图片
    }

    @Override
    protected void setResource(GlideDrawable resource) {
        view.setImageDrawable(resource);  分析25
    }

 ...
}

分析24ImageViewTarget.onResourceReady()

public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z> implements GlideAnimation.ViewAdapter {

    ...

    @Override
    public void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) {
        if (glideAnimation == null || !glideAnimation.animate(resource, this)) {
            setResource(resource);
            // 继续往下看
        }
    }

    protected abstract void setResource(Z resource);
    // setResource()是一个抽象方法
   // 需要在子类具体实现:请回看上面分析25子类GlideDrawableImageViewTarget类重写的setResource():调用view.setImageDrawable(),而这个view就是ImageView
  // 即setResource()的具体实现是调用ImageView的setImageDrawable() 并 传入图片,于是就实现了图片显示。

}

1.3.5 总结

一图总结Glide的基本功能 图片加载的全过程

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值