从源码分析Android的Glide库的图片加载流程及特点

0.基础知识Glide中有一部分单词,我不知道用什么中文可以确切的表达出含义,用英文单词可能在行文中更加合适,还有一些词在Glide中有特别的含义,我理解的可能也不深入,这里先记录一下。

(1)View: 一般情况下,指Android中的View及其子类控件(包括自定义的),尤其指ImageView。这些控件可在上面绘制Drawable(2)Target: Glide中重要的概念,目标。它即可以指封装了一个View的Target(ViewTarget),也可以不包含View(SimpleTarget)。(3)Drawable: 指Android中的Drawable类或者它的子类,如BitmapDrawable等。或者Glide中基础Drawable实现的自定义Drawable(如GifDrawable等)(4)Request – 加载请求,可以是网络请求或者其他任何下载图片的请求,也是Glide中的一个类。(5)Model:数据源的提供者,如Url,文件路径等,可以从model中获取InputStream。(6)Signature:签名,可以唯一地标识一个对象。(7)recycle():Glide中Resource类有此方法,表示该资源不被引用,可以放入池中(此时并没有释放空间)。Android中Bitmap也有此方法,表示释放Bitmap占用的内存。

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

2. 总体设计

基本概念RequestManager:请求管理,每一个Activity都会创建一个RequestManager,根据对应Activity的生命周期管理该Activity上所以的图片请求。Engine:加载图片的引擎,根据Request创建EngineJob和DecodeJob。EngineJob:图片加载。DecodeJob:图片处理。流程图这里是大概的总体流程图, 具体的细节中流程下面继续分析。

3. 核心类介绍

3.1 Gilde 用于保存整个框架中的配置。重要方法:

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

用于创建RequestManager,这里是Glide通过Activity/Fragment生命周期管理Request原理所在,这个类很关键、很关键、很关键,重要的事情我只说三遍。主要原理是创建一个自定义Fragment,然后通过自定义Fragment生命周期操作RequestManager,从而达到管理Request。

3.2 RequestManagerRetriever

RequestManager supportFragmentGet(Context context, FragmentManager fm) { SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm); RequestManager requestManager = current.getRequestManager(); if (requestManager == null) { requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode()); current.setRequestManager(requestManager); } return requestManager;}

这里判断是否只当前RequestManagerFragment是否存在RequestManager,保证一个Activity对应一个RequestManager, 这样有利于管理一个Activity上所有的Request。创建RequestManager的时候会将RequestManagerFragment中的回调接口赋值给RequestManager,达到RequestManager监听RequestManagerFragment的生命周期。

3.3 RequestManager成员变量:(1)Lifecycle lifecycle,用于监听RequestManagerFragment生命周期。(2)RequestTracker requestTracker, 用于保存当前RequestManager所有的请求和带处理的请求。重要方法:

@Override//开始暂停的请求public void onStart() { resumeRequests();}//停止所有的请求@Overridepublic void onStop() { pauseRequests();} //关闭所以的请求@Overridepublic void onDestroy() { requestTracker.clearRequests();} //创建RequestBuildpublic DrawableTypeRequest<String> load(String string) { return (DrawableTypeRequest<String>) fromString().load(string);} public <Y extends Target<TranscodeType>> Y into(Y target) { ... Request previous = target.getRequest(); //停止当前target中的Request。 if (previous != null) { previous.clear(); //这个地方很关键,见Request解析 requestTracker.removeRequest(previous); previous.recycle(); } ... return target;}

3.4 DrawableRequestBuilder 用于创建Request。 这里面包括很多方法,主要是配置加载图片的url、大小、动画、ImageView对象、自定义图片处理接口等。

3.5 Request 主要是操作请求,方法都很简单。

@Overridepublic void clear() { ... if (resource != null) { //这里会释放资源 releaseResource(resource); } ...}

这里的基本原理是当有Target使用Resource(Resource见下文)时,Resource中的引用记数值会加一,当释放资源Resource中的引用记数值减一。当没有Target使用的时候就会释放资源,放进Lrucache中。

3.6 EngineResource实现Resource接口,使用装饰模式,里面包含实际的Resource对象

void release() { if (--acquired == 0) { listener.onResourceReleased(key, this); }}  void acquire() { ++acquired;}  @Overridepublic void recycle() { isRecycled = true; resource.recycle();}

acquire和release两个方法是对资源引用计数;recycle释放资源,一般在Lrucache饱和时会触发。

3.7 Engine(重要) 请求引擎,主要做请求的开始的初始化。3.7.1 load方法这个方法很长,将分为几步分析(1)获取MemoryCache中缓存 首先创建当前Request的缓存key,通过key值从MemoryCache中获取缓存,判断缓存是否存在。

private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) { .... EngineResource<?> cached = getEngineResourceFromCache(key); if (cached != null) { cached.acquire(); activeResources.put(key, new ResourceWeakReference(key, cached, getReferenceQueue())); } return cached;} @SuppressWarnings("unchecked")private EngineResource<?> getEngineResourceFromCache(Key key) { Resource<?> cached = cache.remove(key);  final EngineResource result; ... return result;}

(重点)从缓存中获取的时候使用的cache.remove(key),然后将值保存在activeResources中,然后将Resource的引用计数加一。优点:> 正使用的Resource将会在activeResources中,不会出现在cache中,当MemoryCache中缓存饱和的时候或者系统内存不足的时候,清理Bitmap可以直接调用recycle,不用考虑Bitmap正在使用导致异常,加快系统的回收。(2)获取activeResources中缓存activeResources通过弱引用保存recouse ,也是通过key获取缓存,

private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable)

(3)判断当前的请求任务是否已经存在

EngineJob current = jobs.get(key);if (current != null) { current.addCallback(cb); return new LoadStatus(cb, current);}

如果任务请求已经存在,直接将回调事件传递给已经存在的EngineJob,用于请求成功后触发回调。(4)执行请求任务

EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation, transcoder, diskCacheProvider, diskCacheStrategy, priority);EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);jobs.put(key, engineJob);engineJob.addCallback(cb);engineJob.start(runnable);

3.8 EngineRunnable请求执行Runnable,主要功能请求资源、处理资源、缓存资源。

private Resource<?> decodeFromCache() throws Exception { Resource<?> result = null; try { result = decodeJob.decodeResultFromCache(); } catch (Exception e) { if (Log.isLoggable(TAG, Log.DEBUG)) {  Log.d(TAG, "Exception decoding result from cache: " + e); } }  if (result == null) { result = decodeJob.decodeSourceFromCache(); } return result;}  private Resource<?> decodeFromSource() throws Exception { return decodeJob.decodeFromSource();}

加载DiskCache和网络资源。加载DiskCache包括两个,因为Glide默认是保存处理后的资源(压缩和裁剪后),缓存方式可以自定义配置。如果客户端规范设计,ImageView大小大部分相同可以节省图片加载时间和Disk资源。

3.9 DecodeJobpublic Resource<Z> decodeResultFromCache() throws Exception从缓存中获取处理后的资源。上面有关Key的内容,Key是一个对象,可以获取key和orginKey。decodeResultFromCache就是通过key获取缓存,decodeSourceFromCache()就是通过orginKey获取缓存。private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded)处理和包装资源;缓存资源。保存原资源private Resource<T> cacheAndDecodeSourceData(A data) throws IOException 保存处理后的资源private void writeTransformedToCache(Resource<T> transformed)

3.10 TransformationResource<T> transform(Resource<T> resource, int outWidth, int outHeight);处理资源,这里面出现BitmapPool类,达到Bitmap复用。3.11 ResourceDecoder 用于将文件、IO流转化为Resource3.12 BitmapPool 用于存放从LruCache中remove的Bitmap, 用于后面创建Bitmap时候的重复利用。

4.杂谈Glide的架构扩展性高,但是难以理解,各种接口、泛型,需要一定的学习才能熟练运用。Glide的优点:(1)支持对处理后的资源Disk缓存。(2)通过BitmapPool对Bitmap复用。(3)使用activityResources缓存正在使用的resource,对于BitmapPool饱和移除的Bitmap直接调用recycle加速内存回收。

回味起来却有久久不会退去的余香。

从源码分析Android的Glide库的图片加载流程及特点

相关文章:

你感兴趣的文章:

标签云: