一、导言Glide是一个用于Android平台上媒体管理和图像加载的框架。它封装了媒体解码工具、内存和磁盘缓存、资源池等,向用户公开简单易用的接口。我们可以用它来捕捉、解码和
Glide是一个用于Android平台上媒体管理和图像加载的框架。它封装了媒体解码工具、内存和磁盘缓存、资源池等,向用户公开简单易用的接口。我们可以用它来捕捉、解码和显示视频、图片和GIF动画。如果你用过毕加索,你应该知道Glide的使用方式和毕加索非常相似,甚至很多API都有相同的名字。Glide是一个优秀的图像加载库,它有以下优点:
1.Glide可以监控活动的生命周期管理,更合理地管理图片的加载和发布。
2.加载质量,Picasso默认使用ARGB-8888,Glide默认使用RGB-565,内存占用会减少一半。
3.Glide可以加载Gif图片。
4.缓存策略和加载速度。Picasso缓存的是全尺寸,而Glide缓存的图片和ImageView一样大。Glide的这个特性使得加载显得极快,而Picasso则造成了一些延迟,因为在显示之前需要调整大小。
5.Glide可以通过定制GlideMoudle来完成特殊的加载需求,比如加载加密图片等。接下来,我们将从源代码的角度来探讨Glide的内部原理。
二。源代码Glide.with(……)
让我们看看Gilde的源代码
/**
*通过传入上下文,用Glide开始加载。
*
* & ltp & gt
*使用上下文启动的任何请求将仅应用应用程序级别选项,而不会
*基于生命周期事件启动或停止。一般来说,应该在结果层开始加载
*将用于。如果资源将在子片段的视图中使用,
*应该使用该子片段从{ @ link # with(Android . app . fragment)} }开始加载。同样的,
*如果资源将在父片段的视图中使用,加载应该从
* { @ link # with(Android . app . fragment)}使用父片段。同样,如果资源将被使用
*在活动中的视图中,加载应该从{ @ link # with(Android . app . activity)} }开始。
* & lt/p >
*
* & ltp & gt
*此方法适用于将在正常片段或活动之外使用的资源
*生命周期(例如在服务中,或用于通知缩略图)。
* & lt/p >
*
* @ see # with(Android . app . activity)
* @ see # with(Android . app . fragment)
* @ see # with(Android . support . v4 . app . fragment)
* @ see # with(Android . support . v4 . app . fragment activity)
*
* @param context任何上下文,都不会被保留。
* @返回可用于启动加载的顶级应用程序的RequestManager。
*/
带有(上下文context) {
RequestManagerRetriever retriever = requestmanager retriever . get();返回retriever.get(上下文);
}
/**
*使用Glide开始加载,该加载将绑定到给定的{ @ link Android . app . activity } ’的生命周期,并使用
*给定{ @ link Activity } & # 8217的默认选项。
*
* @param activity要使用的活动。
* @返回可用于启动加载的给定活动的RequestManager。
*/
带有(Activity activity) {
requestmanager retriever retriever = RequestManagerRetriever . get();返回retriever . get(activity);
}
/**
*使用Glide开始加载,这将绑定到give { @ link Android . support . v4 . app . fragmentation activity } ’的生命周期
*并且使用给定的{ @ link Android . support . v4 . app . fragment activity } ’的默认选项。
*
* @param activity要使用的活动。
* @返回可用于启动加载的给定FragmentActivity的RequestManager。
*/
具有(FragmentActivity activity活动)的公共静态RequestManager
RequestManagerRetriever retriever = requestmanager retriever . get();返回retriever . get(activity);
}
/**
*使用Glide开始加载,该加载将绑定到给定的{ @ link Android . app . fragment } ’的生命周期和使用
*给定{ @ link Android . app . fragment } ’的默认选项。
*
* @param fragment要使用的片段。
* @返回可用于启动加载的给定片段的RequestManager。
*/
@TargetApi(Build。版本代码。蜂巢)
带有(android.app.Fragment fragment) {
RequestManagerRetriever retriever = requestmanager retriever . get();返回retriever.get(片段);
}
/**
*使用Glide开始加载,该加载将绑定到给定的{ @ link Android . support . v4 . app . fragment } ’的生命周期和
*使用给定的{ @ link Android . support . v4 . app . fragment } ’的默认选项。
*
* @param fragment要使用的片段。
* @返回可用于启动加载的给定片段的RequestManager。
*/
带有(Fragment fragment) {
RequestManagerRetriever retriever = requestmanager retriever . get();返回retriever.get(片段);
}
摘要:可以传入的参数有
* @ see # with(Android . app . activity)
* @ see # with(Android . app . fragment)
* @ see # with(Android . support . v4 . app . fragment)
* @ see # with(Android . support . v4 . app . fragment activity)
同时,使用Activity/Fragment作为with()参数的好处是,图像加载将与Activity/Fragment的生命周期保持一致。例如,暂停状态将被临时加载,并在恢复时自动重新加载。所以我建议在传递参数的时候把Activity和Fragment传递给Glide而不是Context。
三。原则接下来我想说Glide的原理,下图是glide原理简图。
接下来我想说说滑翔的原理。下图显示了滑翔的原理。
滑行原理图
1。Glide的资源获取组件:
模型:原始资源,如Url、AndroidResourceId、文件等。
数据:中间资源,比如Stream,ParcelFileDescriptor(共享文件时常用Content Provider,实际上是操作系统的文件描述符的封装,有in out err三个值。也有人说是链接建立后的套接字句柄。),等等。
资源:直接使用的资源,包括位图、Drawable等。
2。glide库的资源重用:
Android的内存应用几乎都是在new的时候发生,new的更大的对象(比如位图)更容易触发GC_FOR_ALLOW。所以Glide尽量重用资源,防止不必要的GC_FOR_ALLOC被卡住。
最重要的内存重用是内存LruResourceCache(第一次从网络或磁盘读取资源时,它不会保存在LruCache中,当资源被释放时,即当视图不需要该资源时,它会进入LruCache)
还有BitmapPool(Glide会尽量利用图片池来获取可以重复使用的图片。如果得不到,那就是新的。当LruCache触发器被驱逐时,它将回收从LruCache中消除的位图,并重新使用和回收转换中使用的中间位图)
3。Glide库图片库:
以前是位图复用。只有当长度和宽度相等时,它才能被多路复用。
而后面就是size >: =可以根据需要重用,但是只需要调用reconfigure来调整大小就可以了。
Glide使用AttributeStategy和SizeStrategy来实现两种策略。
图片池收到位图后,按长度、宽度或大小从KeyPool中获取键(对象被重用到极致,甚至在池中使用键),然后每个键对应一个双向链表结构来存储。每个键下可能有许多备用位图。
取出后,缩小图片池中记录的当前大小等。,并执行eraseColor(颜色。TRANSPAENT)操作以确保其可用性。
4。滑行装载启动过程:
1.Glide.with(context)创建RequestManager
请求管理器负责管理当前上下文的所有请求。
上下文可以转移到片段、活动或其他上下文。当片段和活动被转移时,对应于当前页面的活动的生命周期可以被RequestManager监控,从而可以控制请求的暂停、恢复和清除。这里采用的监控方法是在当前活动中添加一个没有视图的片段,这样当活动发生onStart onStop onDestroy时,这个片段的onStart onStop onDestroy就会被触发。
RequestTracker类由RequestManager用来跟踪许多当前页面的请求。弱引用用于保存正在运行的请求,强引用用于保存需要恢复的挂起的请求。
2.Glide.with(上下文)。load(url)创建所需的请求
通常是DrawableTypeRequest,后面可以跟transform、fitCenter、animate、placeholder、error、override、skipMemoryCache、signature等。
如果需要将资源转换为字节数组,可以添加一个位图将其更改为BitmapTypeRequest。
请求是滑动加载图片的执行单元。
3.Glide.with(上下文)。加载(url)。进入(imageview)
在请求的into方法中,将调用请求的begin方法来开始执行。
在EngineJob正式生成并放入引擎执行之前,如果没有提前调用override(width,height)指定需要的宽度和高度,Glide会尝试获取imageview的宽度和高度。如果当前imageview未初始化,无法获取宽度和高度,Glide将等待通过view的viewTreeObserver初始化View后获取宽度和高度,再进行下一步。
5。滑动加载资源:
Glide builder将在初始化Glide时生成一个引擎。
引擎包含LruCache缓存和当前正在使用的活动资源缓存(弱引用)。
主动缓存协助LruCache。当资源从LruCache中取出供使用时,它将从LruCache中移除并进入activicecache。
缓存优先级lrucache >: activeCache
引擎初始化的时候要传入两个ExecutorService,也就是会有两个线程池,一个从DiskCache获取资源,一个从Source获取(通常是下载)资源。
线程的封装单元是EngineJob,它有两个顺序状态:一是CacheState。在这种状态下,它首先进入DiskCacheService执行获取。如果没有找到,就进入SourceState,然后进入SourceService执行下载。
6。滑翔目标:
负责图像加载的回调。
四。摘要以上是Glide的源代码和原理。它的内部操作过于复杂,但正是这种复杂的内部实现使得Glide具有可扩展性。比如可以自定义磁盘缓存策略,自定义ModelLoader实现模型到数据的转换,或者自定义ResourceDecoder和ResourceTranscoder实现资源的解码和转码。用一张图总结一下整个加载过程:
好了,文章到此结束。如果你觉得文章写得好,请给个赞!如果你觉得有值得改进的地方,请给我留言。我会仔细检查,修正不足。谢谢大家比较详细专业的android架构信息。