小菜读Glide3.0 源码----with()和load()

我尽量做到不打错别字,用词准确,不造成阅读障碍。

本文基于Glide3.7.0源码,并不是4.0系列。本系列分为三部分:with()、load()、into();本篇文章只介绍Iwith()和load()两个步骤,因为这两个步骤相对而言比较简单,特别是with(),而into()内容非常复杂,必须单独开一篇,要不然太长了。本文的主要目的在于学习总结,并给需要的人一点帮助,并不奢望多么完美,如有错误,欢迎指出。

一.准备

我们使用最简单的例子:

Glide.with(this).load("字符串地址").into(imageView);  //this为MainActivity

所以我们分析的路径也是最简单的情况,不会过细分析,因为太细的分析我就不敢保证正确了,哭~~~

注意: 我个人把Glide的源码解读分为3+3+3 ,第一个"3"指的是with()、load()、into()这三大步。第二个"3"指的是into()中的的三大步:清除旧的request---->构建新的request---->运行新的request。最后一个"3"指的是获取数据的三步:从内存缓存中拿数据—>从磁盘缓存中拿数据—>从网络拿数据并处理,其中"从网络拿数据并处理"比较麻烦,包含拿数据、解码、转换、存入缓存、回调等步骤。可以看出主要步骤都在into()方法里面,所以into()篇幅最长。本文只是三大步中的前两步:with()和load();

二.with()

主要作用:确定生命周期

with()有很多重载的方法:

public static RequestManager with(Context context){...}
public static RequestManager with(Activity activity){...}
public static RequestManager with(FragmentActivity activity){...}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static RequestManager with(android.app.Fragment fragment){...}
public static RequestManager with(Fragemnt fragment){...}

分为两种:Application的context和非Application的context,前者就不说了,生命周期为整个应用程序的生命周期,后者的生命周期就需要处理了,开头的例子中是Activity的那个,代码如下:

 public static RequestManager with(Activity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(activity);
    }

然后看一下retriever.get(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 {
            assertNotDestroyed(activity);
            android.app.FragmentManager fm = activity.getFragmentManager();
            return fragmentGet(activity, fm);
        }
    }

首先如果是非UI线程或者SDK在3.0以下,就调用get(),传入Application的context;如果都不是,就像例子中一样,则调用fragmentGet(…):

 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
        RequestManagerFragment current = getRequestManagerFragment(fm);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }

说白了就是创建一个新的fragment,因为Fragment和Activity的生命周期是同步的,通过Fragment来监听Activity的生命周期,这是一个小技巧,最后返回一个RequestManager,生命周期是一个监听函数,作为RequestManager的lifecycle属性传入,后面会用到。所以说with()主要作用就是跟踪Activity的生命周期。

三.load()

主要作用:初始化配置或者说是属性配置||准备工作

这个主要作用可能描述的不好,我略读代码后的感受就是做了很多配置,为后面into()方法先配置属性及资源,像是做铺垫。

之前with()返回了一个RequestManager,其中有context、lifecycle等属性,现在执行RequestManager的load()方法了:

//RequestManager.java
public DrawableTypeRequest<String> load(String string) {
        return (DrawableTypeRequest<String>) fromString().load(string);
    }

 public DrawableTypeRequest<String> fromString() {
        return loadGeneric(String.class);
    }

其中load()方法比较简单,就是将string参数作为model传入GenericRequestBuilder的Model属性上,后面会用到。所以主要在loadGeneric(String.class):

//RequestManager.java
private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
        ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);
        ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =
                Glide.buildFileDescriptorModelLoader(modelClass, context);
        if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
            throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for"
                    + " which there is a registered ModelLoader, if you are using a custom model, you must first call"
                    + " Glide#register with a ModelLoaderFactory for your custom model class");
        }

        return optionsApplier.apply(
                new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
                        glide, requestTracker, lifecycle, optionsApplier));
    }

首先是创建了两个ModelLoader:streamModelLoader、fileDescriptorModelLoader,这两个ModelLoader很重要,缓存机制就有这两位的参与。两个Glide.build…(…)方法最后都调用了buildModelLoader(…);方法,前者参数为InputStream.class,后者参数为ParcelFileDescriptor.class,最后都走到了这里:

//Glide.java
return Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass);

public static Glide get(Context context) {
        if (glide == null) {
            synchronized (Glide.class) {
                if (glide == null) {
                    Context applicationContext = context.getApplicationContext();
                    List<GlideModule> modules = new ManifestParser(applicationContext).parse();

                    GlideBuilder builder = new GlideBuilder(applicationContext);
                    for (GlideModule module : modules) {
                        module.applyOptions(applicationContext, builder);
                    }
                    glide = builder.createGlide();
                    for (GlideModule module : modules) {
                        module.registerComponents(applicationContext, glide);
                    }
                }
            }
        }

        return glide;
    }

其中在get(context)中有一句"builder.createGlide()",这里面有new缓存对象:

//Glide.java 
Glide createGlide() {
        if (sourceService == null) {
            final int cores = Math.max(1, Runtime.getRuntime().availableProcessors());
            sourceService = new FifoPriorityThreadPoolExecutor(cores);
        }
        if (diskCacheService == null) {
            diskCacheService = new FifoPriorityThreadPoolExecutor(1);
        }
        MemorySizeCalculator calculator = new MemorySizeCalculator(context);
        if (bitmapPool == null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                int size = calculator.getBitmapPoolSize();
                bitmapPool = new LruBitmapPool(size);
            } else {
                bitmapPool = new BitmapPoolAdapter();
            }
        }
        if (memoryCache == null) {
          //缓存对象
            memoryCache = new LruResourceCache(calculator.getMemoryCacheSize());
        }
        if (diskCacheFactory == null) {
          //磁盘缓存工厂
            diskCacheFactory = new InternalCacheDiskCacheFactory(context);
        }
        if (engine == null) {
          //new一个Engin对象,这个对象在into()中会用到
            engine = new Engine(memoryCache, diskCacheFactory, diskCacheService, sourceService);
        }
        if (decodeFormat == null) {
            decodeFormat = DecodeFormat.DEFAULT;
        }
        return new Glide(engine, memoryCache, bitmapPool, context, decodeFormat);
    }

其中new了一个LruResourceCache(…)的缓存,获得了一个diskCacheFactory,还new了一个engine对象并将获得的cache、factory等等传入进去了,这个Engin在后期into(…)会用到;最后返回一个glide对象,然后用这个对象去创建modelLoader;这个new Glide(…);里面做了非常多的操作,其中注册了许多的工厂。

//Glide.java
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
        this.engine = engine;
        this.bitmapPool = bitmapPool;
        this.memoryCache = memoryCache;
        this.decodeFormat = decodeFormat;
        loaderFactory = new GenericLoaderFactory(context);
        mainHandler = new Handler(Looper.getMainLooper());
        bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);

        dataLoadProviderRegistry = new DataLoadProviderRegistry();

        StreamBitmapDataLoadProvider streamBitmapLoadProvider =
                new StreamBitmapDataLoadProvider(bitmapPool, decodeFormat);
        dataLoadProviderRegistry.register(InputStream.class, Bitmap.class, streamBitmapLoadProvider);

        FileDescriptorBitmapDataLoadProvider fileDescriptorLoadProvider =
                new FileDescriptorBitmapDataLoadProvider(bitmapPool, decodeFormat);
        dataLoadProviderRegistry.register(ParcelFileDescriptor.class, Bitmap.class, fileDescriptorLoadProvider);

        ImageVideoDataLoadProvider imageVideoDataLoadProvider =
                new ImageVideoDataLoadProvider(streamBitmapLoadProvider, fileDescriptorLoadProvider);
        dataLoadProviderRegistry.register(ImageVideoWrapper.class, Bitmap.class, imageVideoDataLoadProvider);

        GifDrawableLoadProvider gifDrawableLoadProvider =
                new GifDrawableLoadProvider(context, bitmapPool);
        dataLoadProviderRegistry.register(InputStream.class, GifDrawable.class, gifDrawableLoadProvider);

        dataLoadProviderRegistry.register(ImageVideoWrapper.class, GifBitmapWrapper.class,
                new ImageVideoGifDrawableLoadProvider(imageVideoDataLoadProvider, gifDrawableLoadProvider, bitmapPool));

        dataLoadProviderRegistry.register(InputStream.class, File.class, new StreamFileDataLoadProvider());
        //一大片的注册
        register(File.class, ParcelFileDescriptor.class, new FileDescriptorFileLoader.Factory());
        register(File.class, InputStream.class, new StreamFileLoader.Factory());
        register(int.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory());
        register(int.class, InputStream.class, new StreamResourceLoader.Factory());
        register(Integer.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory());
        register(Integer.class, InputStream.class, new StreamResourceLoader.Factory());
        register(String.class, ParcelFileDescriptor.class, new FileDescriptorStringLoader.Factory());
        register(String.class, InputStream.class, new StreamStringLoader.Factory());
        register(Uri.class, ParcelFileDescriptor.class, new FileDescriptorUriLoader.Factory());
        register(Uri.class, InputStream.class, new StreamUriLoader.Factory());
        register(URL.class, InputStream.class, new StreamUrlLoader.Factory());
        //其中最重要的是这个工厂
        register(GlideUrl.class, InputStream.class, new HttpUrlGlideUrlLoader.Factory());
        register(byte[].class, InputStream.class, new StreamByteArrayLoader.Factory());

        transcoderRegistry.register(Bitmap.class, GlideBitmapDrawable.class,
                new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool));
        //Gif相关
        //......
    }

其中最重要的是注册了许多的工厂,具体是什么工厂,你看名字也猜出个大概,这也是Java命名规则的好处之一,

所有工厂中最重要的目前是HttpUrlGlideUrlLoader.Factory(),这是真正网络访问获取图片时需要用到的。register(…)方法如下:

//GenericLoaderFactory.java
public synchronized <T, Y> ModelLoaderFactory<T, Y> register(Class<T> modelClass, Class<Y> resourceClass,
        ModelLoaderFactory<T, Y> factory) {
    cachedModelLoaders.clear();

    Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass);
    if (resourceToFactories == null) {
        resourceToFactories = new HashMap<Class/*Y*/, ModelLoaderFactory/*T, Y*/>();
        modelClassToResourceFactories.put(modelClass, resourceToFactories);
    }

    ModelLoaderFactory/*T, Y*/ previous = resourceToFactories.put(resourceClass, factory);
    //...
    return previous;
}

可以看到创建了一个resourceFactories的map,然后把factory参数put进去。

到这里为止,创建了两个modelLoader,这里面把缓存配置好了,网络访问的工厂准备好了,还有很多配置,接下来往下走:

//RequestManager.java
return optionsApplier.apply(
                new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
                        glide, requestTracker, lifecycle, optionsApplier));

optionsApplier.apply(…)这个方法我不是很理解,主要是配置options这个属性的,注释说是配置一些默认选项,但我没找到设置的地方,哭~,所以在我看来基本结果就是"给啥返啥",给了DrawableTypeRequest就返给你DrawableTypeRequest,那重点就是这个返回的对象做了什么初始化操作?

//DrawableTypeRequest.java
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,
                buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
                        GlideDrawable.class, null),
                glide, requestTracker, lifecycle);
        this.streamModelLoader = streamModelLoader;
        this.fileDescriptorModelLoader = fileDescriptorModelLoader;
        this.optionsApplier = optionsApplier;
    }

其他的都简单,最重要的就是builderProvider(…),相信你也看出来了,这个方法传入了2个modelLoader、lifecycle、glide等重要参数,返回一个FixedLoadProvider对象,我觉得这里先不要管这个provider具体是干嘛的,要不然容易绕死,只记住返回了一个provider,先进入super(…)方法,:

//DrawabloeRequestBuilder.java
DrawableRequestBuilder(Context context, Class<ModelType> modelClass,
            LoadProvider<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> loadProvider, Glide glide,
            RequestTracker requestTracker, Lifecycle lifecycle) {
        super(context, modelClass, loadProvider, GlideDrawable.class, glide, requestTracker, lifecycle);
        // Default to animating.
        crossFade();
    }

现在进入了DrawableRequestBuilder.java中,又是super(…)方法:

//GenericRequestBuilder.java
GenericRequestBuilder(Context context, Class<ModelType> modelClass,
            LoadProvider<ModelType, DataType, ResourceType, TranscodeType> loadProvider,
            Class<TranscodeType> transcodeClass, Glide glide, RequestTracker requestTracker, Lifecycle lifecycle) {
        this.context = context;
        this.modelClass = modelClass;
        this.transcodeClass = transcodeClass;
        this.glide = glide;
        this.requestTracker = requestTracker;
        this.lifecycle = lifecycle;
        this.loadProvider = loadProvider != null
                ? new ChildLoadProvider<ModelType, DataType, ResourceType, TranscodeType>(loadProvider) : null;

        if (context == null) {
            throw new NullPointerException("Context can't be null");
        }
        if (modelClass != null && loadProvider == null) {
            throw new NullPointerException("LoadProvider must not be null");
        }
    }

这里进入到了GenericRequestBuilder.java 中,这个类很重要,我们三大步中的最后一步——into(…)就是从这里开始的,也就是"3+3+3"中第二个"3"的所在地。可以看到这里传入了非常多的参数作为属性,之前准备的provider、glide、lifecycle、context等等都到了这里,并没有什么复杂的操作,感觉就是为之后的into(…)做准备。

​ 接下来回头看buildProvider(…)方法:

//DrawableTypeRequest.java
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 (streamModelLoader == null && fileDescriptorModelLoader == null) {
            return null;
        }

        if (transcoder == null) {
            transcoder = glide.buildTranscoder(resourceClass, transcodedClass);
        }
        DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class,
                resourceClass);
        ImageVideoModelLoader<A> modelLoader = new ImageVideoModelLoader<A>(streamModelLoader,
                fileDescriptorModelLoader);
        return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);
    }

注意第二个判null,因为我们传进来的就是null,所以这里会进入判断内部去创建一个转换器,用于获取数据以后使用,然后创建了一个dataLoadProvider和modelLoader,前者保存有网络获取的数据流InputStream之类的,在ImageVideoWrapper.class里,后者是into(…)步骤中里真正调用工厂去网络访问的对象,最后这些都会被放入FixedLoadProvider()中。给我的感觉就是准备好了获取数据的对象、准备好了承接inputStream的类、准备好了对数据结果进行转换的类,最后汇集一下,等使用的时候在调用。

​ 整个load(…)步骤大概就这些,其中我认为最重要的就是两个modelLoader:streamModelLoader、fileDescriptorModelLoader,这两个对象对下连接缓存,对上连接数据流,还和网络访问和数据转换在一起搞基,感觉挺厉害,希望重点研究。

设置

使用时经常指定"asBitmap()、asGif()",这两个方法会导致生成不同的"request",后期处理生成不同的对象。

还有"placeholder(…)、error(…)"等,这些方法都是在DrawableRequestBuilder.java中,因为load(…)方法只返回DrawableTypeRequest,而它继承了DrawableRequestBuilder.java,而后者又继承GenericRequestBuilder.java 这个特别重要的类,一个super(…)把所有的东西都扔给你,into(…)步骤时就可以使用了。

关于into(…)的文章在这里:小菜读Glide3.0源码----into()
感谢:

https://blog.csdn.net/guolin_blog/article/details/53939176

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值