频道栏目
首页 > 程序开发 > 移动开发 > Android > 正文
Android Glide
2017-09-13 10:37:00      个评论    来源:Style Thinks的博客  
收藏   我要投稿

Glide的特点

区别于其它的第三方加载库,它可以与activity、fragment的生命周期绑定,在Paused暂停加载,在Resumed的时候又自动重新加载。

支持Memory和Disk图片缓存

支持Gif和Webp格式图片

使用Bitmap Pool可以使Bitmap复用

对于回收的Bitmap会制动调用recycle,减少系统回收压力

总体设计

基本概念

RequestManager:请求管理,每一个Activity都会创建一个RequestManager,根据对应Activity的生命周期管理该Activity上所有的图片请求

Engine:加载图片的引擎,根据Request创建EngineJob和DecodeJob

EngineJob:图片加载

DecodeJob:图片处理

核心类介绍

3.1 Clide

用于保存整个框架中的配置。

重要方法:

public static RequestManager with(Context context) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(context); }

用于创建RequsetManager,这里是Glide通过Activity/Fragment生命周期管理Request的原理所在,整个类很关键,主要原理是创建一个自定义的Fragment,然后通过自定义Fragment生命周期操作RequestManager,从而达到管理request。

这里会将RequestManagerFragment生命周期事件回调通过RequestManager的构造函数传值。所以RequestManage就能响应RequestManagerFragment的生命周期

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

成员变量:

Lifecycle lifecycle,用于监听RequestManagerFragment生命周期。

RequestTracker requestTracker, 用于保存当前RequestManager所有的请求和带处理的请求。

重要方法:

/** * Lifecycle callback that registers for connectivity events (if the android.permission.ACCESS_NETWORK_STATE * permission is present) and restarts failed or paused requests. */ @Override public void onStart() { // onStart might not be called because this object may be created after the fragment/activity's onStart method. resumeRequests(); } /** * Lifecycle callback that unregisters for connectivity events (if the android.permission.ACCESS_NETWORK_STATE * permission is present) and pauses in progress loads. */ @Override public void onStop() { pauseRequests(); } /** * Lifecycle callback that cancels all in progress requests and clears and recycles resources for all completed * requests. */ @Override public void onDestroy() { requestTracker.clearRequests(); } .... /** * Returns a request builder that uses the {@link com.bumptech.glide.load.model.ModelLoaderFactory}s currently * registered for the given model class for {@link InputStream}s and {@link ParcelFileDescriptor}s to load a * thumbnail from either the image or the video represented by the given model. * *

* Note - for maximum efficiency, consider using {@link #from(Class)}} to avoid repeatedly allocating builder * objects. *

* * @see #from(Class) * * @param model The model the load. * @param The type of the model to load. */ public DrawableTypeRequest load(T model) { return (DrawableTypeRequest) loadGeneric(getSafeClass(model)).load(model); } ......... public > 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

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

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

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

3.7 EngineResource

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

1. void release() { 2. if (--acquired == 0) { 3. listener.onResourceReleased(key, this); 4. } 5. } 6. 7. void acquire() { 8. ++acquired; 9. } 10. 11. @Override 12. public void recycle() { 13. isRecycled = true; 14. resource.recycle(); 15. }

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

3.8 Engine(重要)

请求引擎,主要做请求的开始的初始化。

3.8.1 load方法

这个方法很长,将分为几步分析

获取MemoryCache中缓存

首先创建当前Request的缓存key,通过key值从MemoryCache中获取缓存,判断缓存是否存在。

1. private EngineResourceloadFromCache(Key key, boolean isMemoryCacheable) { 2. .... 3. EngineResourcecached = getEngineResourceFromCache(key); 4. if (cached != null) { 5. cached.acquire(); 6. activeResources.put(key, new ResourceWeakReference(key, cached, getReferenceQueue())); 7. } 8. return cached; 9. } 10. 11. @SuppressWarnings("unchecked") 12. private EngineResourcegetEngineResourceFromCache(Key key) { 13. Resourcecached = cache.remove(key); 14. 15. final EngineResource result; 16. ... 17. return result; 18. }

(重点)从缓存中获取的时候使用的cache.remove(key),然后将值保存在activeResources中,然后将Resource的引用计数加一。

优点:

正使用的Resource将会在activeResources中,不会出现在cache中,当MemoryCache中缓存饱和的时候或者系统内存不足的时候,清理Bitmap可以直接调用recycle,不用考虑Bitmap正在使用导致异常,加快系统的回收。

获取activeResources中缓存

activeResources通过弱引用保存recouse ,也是通过key获取缓存,

1. private EngineResourceloadFromActiveResources(Key key, boolean isMemoryCacheable)

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

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

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

执行请求任务

1. EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable); 2. DecodeJob decodeJob = new DecodeJob(key, width, height, fetcher, loadProvider, transformation, 3. transcoder, diskCacheProvider, diskCacheStrategy, priority); 4. EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority); 5. jobs.put(key, engineJob); 6. engineJob.addCallback(cb); 7. engineJob.start(runnable);

3.9 EngineRunnable

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

1. private ResourcedecodeFromCache() throws Exception { 2. Resourceresult = null; 3. try { 4. result = decodeJob.decodeResultFromCache(); 5. } catch (Exception e) { 6. if (Log.isLoggable(TAG, Log.DEBUG)) { 7. Log.d(TAG, "Exception decoding result from cache: " + e); 8. } 9. } 10. 11. if (result == null) { 12. result = decodeJob.decodeSourceFromCache(); 13. } 14. return result; 15. } 16. 17. private ResourcedecodeFromSource() throws Exception { 18. return decodeJob.decodeFromSource(); 19. }

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

3.10 DecodeJob

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

3.11 Transformation

1. Resource transform(Resource resource, int outWidth, int outHeight);

处理资源,这里面出现BitmapPool类,达到Bitmap复用。

3.12 ResourceDecoder

用于将文件、IO流转化为Resource

3.13BitmapPool

用于存放从LruCache中remove的Bitmap, 用于后面创建Bitmap时候的重复利用。

点击复制链接 与好友分享!回本站首页
上一篇:Android shape的用法
下一篇:Android签名机制之---签名过程详解
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站