写在以前html
上一篇博文写的是Picasso基本使用和源码彻底解析,Picasso的源码阅读起来仍是很顺畅的,而后就想到Glide框架,网上你们也都推荐使用这个框架用来加载图片,正好我目前的写做目标也是分析当前一些流行的框架源码,那就也来解析下Glide的源码吧,并且有了Picasso源码的分析相信很快就搞定Glide的,结果也就悲剧了,深陷其中没法自拔了,Glide的源码远非Picasso能比,阅读起来也是至关的困难的,并且我使用的是最新的Glide4.0,与以前版本有较大的差别,网上也没能够参考的资料,这就悲剧了,苦头专研呗。直到今天才从深沟中冒出头了,差点憋死,哈哈。python
正文git
Glide的使用和Picasso基本同样,这里就再也不多说,主要是由于源码分析会写的很长很细,再加上基本使用的话,就更加长了,并且上一篇已写过Picasso的基本使用,这二者在使用方面相差的微乎及微,因此咱们这篇文章直接进入源码分析。github
首先在build.gradle里添加以下引用:设计模式
compile 'com.github.bumptech.glide:glide:4.0.0-RC0'
这里我用的是Glide4.0也是最新的版本,和3.X在源码上仍是有很大的差异的。看过3.X源码的相信对比下这篇文章就会知道。缓存
ok,和Picasso的分析模式同样,咱们也是从下面最简单的代码进行一步一步的深刻分析:微信
Glide.with(MainActivity.this).load(url).into(headerImage);
首先咱们来看看当咱们调用Glide的with方法那作了哪些工做:网络
with方法中能够接受Context,Activity,FragmentActivity,Fragment甚至是View不一样的类型,返回的是RequestManager对象,这个对象是须要在RequestManagerRetriever中获取的,那咱们在来看看RequestManagerRetriever是怎么获取到的?请看getRetriever方法的源码:app
getRetriever方法中也没有真正的建立RequestManagerRetriever对象,而是从Glide的getRequestManagerRetriever方法中获取,那么很明显的能够看出所作的工做都是在Glide的get方法中完成的,在来看下get方法源码:框架
来到这一步,咱们看到了很是熟悉的代码设计原理,那就是双重加锁的单例模式保证Glide对象的惟一性,那么initGlide就是建立Glide对象的方法了,请看:
这是initGlide方法中最重要的代码,主要是建立了一个GlideBuilder对象,而后调用build方法来完成Glide对象的建立,相信不用看bulid方法,你们也会猜到接下来将要发生什么样的事情,没错,那就是使用建造者设计模式来完美的构建出Glide对象:
public Glide build(Context context) { if (sourceExecutor == null) { sourceExecutor = GlideExecutor.newSourceExecutor(); } if (diskCacheExecutor == null) { diskCacheExecutor = GlideExecutor.newDiskCacheExecutor(); } if (memorySizeCalculator == null) { memorySizeCalculator = new MemorySizeCalculator.Builder(context).build(); } if (connectivityMonitorFactory == null) { connectivityMonitorFactory = new DefaultConnectivityMonitorFactory(); } if (bitmapPool == null) { int size = memorySizeCalculator.getBitmapPoolSize(); bitmapPool = new LruBitmapPool(size); } 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()); } RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever( requestManagerFactory); return new Glide( context, engine, memoryCache, bitmapPool, arrayPool, requestManagerRetriever, connectivityMonitorFactory, logLevel, defaultRequestOptions.lock()); }
build方法中主要是构建线程池(包括sourceExecutor ,diskCacheExecutor ),缓存大小和缓存器,默认的链接监听工厂(connectivityMonitorFactory ),Engine对象和RequestManagerRetriever 对象等等。
有几个重要的对象建立,咱们这里先看下它的构建内容:
1 Engine对象
建立Engine对象在构造方法中传递了几个重要的参数,分别是线程池,内存缓存和硬盘缓存对象,那咱们来看看在构造方法中它是怎么构建Engine对象的:
Engine(MemoryCache cache, DiskCache.Factory diskCacheFactory, GlideExecutor diskCacheExecutor, GlideExecutor sourceExecutor, GlideExecutor sourceUnlimitedExecutor, Map<Key, EngineJob<?>> jobs, EngineKeyFactory keyFactory, Map<Key, WeakReference<EngineResource<?>>> activeResources, EngineJobFactory engineJobFactory, DecodeJobFactory decodeJobFactory, ResourceRecycler resourceRecycler) { this.cache = cache; this.diskCacheProvider = new LazyDiskCacheProvider(diskCacheFactory); if (activeResources == null) { activeResources = new HashMap<>(); } this.activeResources = activeResources; if (keyFactory == null) { keyFactory = new EngineKeyFactory(); } this.keyFactory = keyFactory; if (jobs == null) { jobs = new HashMap<>(); } this.jobs = jobs; if (engineJobFactory == null) { engineJobFactory = new EngineJobFactory(diskCacheExecutor, sourceExecutor, sourceUnlimitedExecutor, this); } this.engineJobFactory = engineJobFactory; if (decodeJobFactory == null) { decodeJobFactory = new DecodeJobFactory(diskCacheProvider); } this.decodeJobFactory = decodeJobFactory; if (resourceRecycler == null) { resourceRecycler = new ResourceRecycler(); } this.resourceRecycler = resourceRecycler; cache.setResourceRemovedListener(this); }
建立了几个工厂对象方法,好比EngineKeyFactory,EngineJobFactory和DecodeJobFactory,几个HashMap类型的对象集合,如:jobs ,activeResources 等等,而后就分别把这些对象赋值给Engine的成员变量,那么来看下建立Engine对象时到底初始化了那些成员变量:
ok,Engine是一个很是重要的对象,后面扮演着重要的角色,为了方面理解它所拥有那些可以使用的对象,这里我作了个类图显示的标了出来。
2 RequestManagerRetriever 对象
再来看看RequestManagerRetriever 对象的建立,这个相对的简单不少,咱们来看下它的构造方法:
因为咱们传递过来的requestManagerFactory为空,因此factory将会使用默认的DEFAULT_FACTORY工厂,DEFAULT_FACTORY是真正建立RequestManager对象的地方,稍后介绍。
这里只是让你们知道这里的factory就是DEFAULT_FACTORY。
来看看它拥有哪些成员:
3 Glide对象
在build方法中 return new Gilde(),建立一个Glide对象并返回,那在Gilde构造方法中作了哪些初始化工做呢?
Glide( Context context, Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, ArrayPool arrayPool, RequestManagerRetriever requestManagerRetriever, ConnectivityMonitorFactory connectivityMonitorFactory, int logLevel, RequestOptions defaultRequestOptions) { this.engine = engine; this.bitmapPool = bitmapPool; this.arrayPool = arrayPool; this.memoryCache = memoryCache; this.requestManagerRetriever = requestManagerRetriever; this.connectivityMonitorFactory = connectivityMonitorFactory; DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT); bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat); final Resources resources = context.getResources(); registry = new Registry(); registry.register(new DefaultImageHeaderParser()); registry.register()...append()... ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory(); glideContext = new GlideContext(context, registry, imageViewTargetFactory, defaultRequestOptions, engine, this, logLevel); }
这里首先是把传递进来的参数赋值给成员变量,而后建立了几个重要的对象:
①:Registry对象
Registry主要是添加不少的注册或解析方式等,这在后面用来解析是从内存,文件或是网络获取资源有着重要的做用,并且它每一类解析方式都会提供多个方法,一种方式获取不到将会使用另一种,知道获取到资源为止,来看下它的register和append方法:
主要是存放到不一样的对象中的集合变量中。
②:GlideContext对象
GlideContext对象在后面也扮演中重要的角色,建立这个对象到目前为止只是为了初始化和赋值:
总结下Glide,Registry和GlideContext对象所初始化的参数:
这是到目前对象所拥有的成员方法和成员变量。
ok,再回到上面build方法,在返回Glide对象后,调用getRequestManagerRetriever()从而获取到RequestManagerRetriever对象,从上面Glide类图咱们也能够看出,Glide对象已包含RequestManagerRetriever对象。
再往上返回一步,在getRetriever(activity)方法中获取到RequestManagerRetriever对象后,调用get(activity)来获取RequestManager对象,那么咱们来看看它是怎么获取到的?
首先判断是否在子线程执行,不然就调用supportFragmentGet方法来获取RequestManager对象,那么来看下它的源码:
还记得咱们的RequestManagerRetriever拥有哪些成员吗,不记得就去看看上面它的类图吧,由它的源码咱们能够看到它将会使用factory并调用它的build方法,还记得factory是什么吗?上面已分析factory就是DEFAULT_FACTORY,那来看看它的源码实现:
在build中建立一个RequestManager对象并返回,来看下RequestManager的构造方法中作了哪些操做:
RequestManager( Glide glide, Lifecycle lifecycle, RequestManagerTreeNode treeNode, RequestTracker requestTracker, ConnectivityMonitorFactory factory) { this.glide = glide; this.lifecycle = lifecycle; this.treeNode = treeNode; this.requestTracker = requestTracker; final Context context = glide.getGlideContext().getBaseContext(); connectivityMonitor = factory.build(context, new RequestManagerConnectivityListener(requestTracker)); if (Util.isOnBackgroundThread()) { mainHandler.post(addSelfToLifecycle); } else { lifecycle.addListener(this); } lifecycle.addListener(connectivityMonitor); setRequestOptions(glide.getGlideContext().getDefaultRequestOptions()); glide.registerRequestManager(this); }
主要是赋值,添加生命周期监听器,设置请求属性,以及注册请求管理器,代码仍是很简单的,都能看的明白。
来看下它的类图:
ok,到此,咱们的with方法中获取RequestManager对象就已完成。
来看下with方法执行的顺序图:
注:流程图看不清楚,能够选择在“新标签中打开图片”查看。
在调用with方法获取到RequestManager对象的前提下,调用load方法,并传递咱们的url参数,来看下它的源码:
这里并无直接的去加载咱们的url获取资源,而是首先调用asDrawable方法来配置图片的信息,其实就是说加载获取的图片资源是转换为drawale或是bitmap或是gif进行图片显示,默认的是使用drawale,你也可使用asGif()/asBitmap()来设置它是已什么形式来展现。这里咱们按默认的方式来分析。
load方法目的是为了获取RequestBuilder对象,下面来一步步分解它源码:
首先来看下asDrawable()的源码:
asDrawable()中首先调用as方法,并传进Drawable.class做为参数,来看下as方法的源码:
由as方法,咱们可看到它直接的建立一个RequestBuilder对象,并传递了相关的参数进去,这里要注意下resourceClass就是Drawable.class这里在后面有个选择分支时使用到。
来看下RequestBuilder的构造方法中作了哪些初始化布局。
很简单的赋值,这里也须要注意的是transcodeClass就是Drawable.class类。
ok,获取到RequestBuilder对象后,它又作了进一步的赋值操做,就是在transition方法中,
把建立的DrawableTransitionOptions对象赋值给transitionOptions变量。
ok,再往上来看,完成asDrawable方法对RequestBuilder的建立后才调用load方法来传递咱们的url地址,其实在load也没有作什么事,就是一个中转站,转给了loadGeneric方法,来看:
在loadGeneric方法中也没作其余太多的操做,也是保存了咱们的url而且isModelSet设置为true,意思就是说Model已有设置了。来看下它的类图:
它到目前为止所包含的成员变量和方法都在此。
ok,到此咱们的load方法也分析完毕,来看下它的流程图:
注:流程图看不清楚,能够选择在“新标签中打开图片”查看。
因为Glide源码非常复杂,写的很长,因此只能分两篇来发布,第一篇分析了Glide的with和load方法源码,第二篇将会分析into方法,说实在的into方法复杂程度远超过with和load方法总和,可是不要紧,仍是保持一向的风格,一步步的分析其执行流程,相信你们学完确定能彻底的掌握它的源码结构。
ok,今天就先发布这一篇吧。
各位若是还有哪里不明白的,或是我这里讲的还不够透彻,亦或是讲错了的地方请留言指正,让咱们共同进步,谢谢
同时,请你们扫一扫关注个人微信公众号,虽然写的不是很勤,可是每一篇都有质量保证,让您学习到真正的知识。