glide原理_分享glide使用教程

glide原理_分享glide使用教程,第1张

glide原理_分享glide使用教程 一、前言Glide 是安卓平台上媒体管理和图片加载框架,它内部封装了媒体解码工具、内存和磁盘缓存以及资源池等,并向用户暴露简单易用的接口。

我们可以用它来获取、解码、并展示视频、图片和 GIF 动画。

如果大家有用过 Picasso 应该知道,Glide 的使用方式和 Picasso 非常相似,甚至很多 API 的名称都一样。

Glide是一个优秀的图片加载库,它有如下优点:1. Glide可以监听Activity的生命周期管理,更加合理的管理图片的加载和释放。

2. 加载质量,Picasso默认采用的ARGB-8888, Glide默认采用的是RGB-565,内存占用会减小一半。

3. Glide可以加载Gif图。

4. 缓存策略和加载速度。

Picasso缓存的是全尺寸,而Glide的缓存的图片和ImageView的尺寸相同。

Glide的这个特点,让加载显得特别的快,而Picasso则因为需要在显示之前重新调整大小而导致一些延迟。

5. Glide可以通过自定义GlideMoudle来完成特殊的加载需求,例如加载加密的图片等。

接下来我们就从源码的角度来探究一下 Glide 的内部原理。

二、源码Glide.with(……)我们来看一下Gilde的源码/*** Begin a load with Glide by passing in a context.** <p>* Any requests started using a context will only have the application level options applied and will not be* started or stopped based on lifecycle events. In general, loads should be started at the level the result* will be used in. If the resource will be used in a view in a child fragment,* the load should be started with {@link #with(android.app.Fragment)}} using that child fragment. Similarly,* if the resource will be used in a view in the parent fragment, the load should be started with* {@link #with(android.app.Fragment)} using the parent fragment. In the same vein, if the resource will be used* in a view in an activity, the load should be started with {@link #with(android.app.Activity)}}.* </p>** <p>* This method is appropriate for resources that will be used outside of the normal fragment or activity* lifecycle (For example in services, or for notification thumbnails).* </p>** @see #with(android.app.Activity)* @see #with(android.app.Fragment)* @see #with(android.support.v4.app.Fragment)* @see #with(android.support.v4.app.FragmentActivity)** @param context Any context, will not be retained.* @return A RequestManager for the top level application that can be used to start a load.*/public static RequestManager with(Context context) {RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(context);}/*** Begin a load with Glide that will be tied to the given {@link android.app.Activity}’s lifecycle and that uses the* given {@link Activity}’s default options.** @param activity The activity to use.* @return A RequestManager for the given activity that can be used to start a load.*/public static RequestManager with(Activity activity) {RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(activity);}/*** Begin a load with Glide that will tied to the give {@link android.support.v4.app.FragmentActivity}’s lifecycle* and that uses the given {@link android.support.v4.app.FragmentActivity}’s default options.** @param activity The activity to use.* @return A RequestManager for the given FragmentActivity that can be used to start a load.*/public static RequestManager with(FragmentActivity activity) {RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(activity);}/*** Begin a load with Glide that will be tied to the given {@link android.app.Fragment}’s lifecycle and that uses* the given {@link android.app.Fragment}’s default options.** @param fragment The fragment to use.* @return A RequestManager for the given Fragment that can be used to start a load.*/@TargetApi(Build.VERSION_CODES.HONEYCOMB)public static RequestManager with(android.app.Fragment fragment) {RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(fragment);}/*** Begin a load with Glide that will be tied to the given {@link android.support.v4.app.Fragment}’s lifecycle and* that uses the given {@link android.support.v4.app.Fragment}’s default options.** @param fragment The fragment to use.* @return A RequestManager for the given Fragment that can be used to start a load.*/public static RequestManager with(Fragment fragment) {RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(fragment);}总结:可以传入的参数有*@see #with(android.app.Activity)* @see #with(android.app.Fragment)* @see #with(android.support.v4.app.Fragment)* @see #with(android.support.v4.app.FragmentActivity)同时将Activity/Fragment作为with()参数的好处是:图片加载会和Activity/Fragment的生命周期保持一致,比如Paused状态在暂停加载,在Resumed的时候又自动重新加载。

所以我建议传参的时候传递Activity 和 Fragment给Glide,而不是Context。

三、原理接下来我想说Glide的原理,下图是glide原理简图。

glide原理简图1.Glide的资源获取组件:· Model: 原始资源,比如Url,AndroidResourceId, File等· Data: 中间资源,比如Stream,ParcelFileDescriptor(ContentProvider共享文件时比较常用,其实就是 *** 作系统的文件描述符的封装,里面有in out err三个取值。

也有人说是链接建立好之后的socket句柄。

)等· Resource:直接使用的资源,包括Bitmap,Drawable等2.Glide库的资源复用:· Android的内存申请几乎都在new的时候发生,而new较大对象(比如Bitmap时),更加容易触发GC_FOR_ALLOW。

所以Glide尽量的复用资源来防止不必要的GC_FOR_ALLOC引起卡顿。

· 最显著的内存复用就是内存LruResourceCache(第一次从网络或者磁盘上读取到Resource时,并不会保存到LruCache当中,当Resource被release时,也就是View不在需要此Resource时,才会进入LruCache当中)· 还有BitmapPool(Glide会尽量用图片池来获取到可以复用的图片,获取不到才会new,而当LruCache触发Evicted时会把从LruCache中淘汰下来的Bitmap回收,也会把transform时用到的中间Bitmap加以复用及回收)3.Glide库图片池:· 以前是Bitmap复用必须长宽相等才可以复用· 及以后是Size>=所需就可以复用,只不过需要调用reconfigure来调整尺寸· Glide用AttributeStategy和SizeStrategy来实现两种策略· 图片池在收到传来的Bitmap之后,通过长宽或者Size来从KeyPool中获取Key(对象复用到了极致,连Key都用到了Pool),然后再每个Key对应一个双向链表结构来存储。

每个Key下可能有很多个待用Bitmap· 取出后要减少图片池中记录的当前Size等,并对Bitmap进行eraseColor(Color.TRANSPAENT) *** 作确保可用4.Glide加载发起流程:1. Glide.with(context)创建RequestManager· RequestManager负责管理当前context的所有Request· Context可以传Fragment、Activity或者其他Context,当传Fragment、Activity时,当前页面对应的Activity的生命周期可以被RequestManager监控到,从而可以控制Request的pause、resume、clear。

这其中采用的监控方法就是在当前activity中添加一个没有view的fragment,这样在activity发生onStart onStop onDestroy的时候,会触发此fragment的onStart onStop onDestroy。

· RequestManager用来跟踪众多当前页面的Request的是RequestTracker类,用弱引用来保存运行中的Request,用强引用来保存暂停需要恢复的Request。

2. Glide.with(context).load(url)创建需要的Request· 通常是DrawableTypeRequest,后面可以添加transform、fitCenter、animate、placeholder、error、override、skipMemoryCache、signature等等· 如果需要进行Resource的转化比如转化为Byte数组等需要,可以加asBitmap来更改为BitmapTypeRequest· Request是Glide加载图片的执行单位3. Glide.with(context).load(url).into(imageview)· 在Request的into方法中会调用Request的begin方法开始执行· 在正式生成EngineJob放入Engine中执行之前,如果并没有事先调用override(width, height)来指定所需要宽高,Glide则会尝试去获取imageview的宽和高,如果当前imageview并没有初始化完毕取不到高宽,Glide会通过view的ViewTreeObserver来等View初始化完毕之后再获取宽高再进行下一步5.Glide加载资源:· GlideBuilder在初始化Glide时,会生成一个执行机Engine· Engine中包含LruCache缓存及一个当前正在使用的active资源Cache(弱引用)· activeCache辅助LruCache,当Resource从LruCache中取出使用时,会从LruCache中remove并进入acticeCache当中· Cache优先级LruCache>activeCache· Engine在初始化时要传入两个ExecutorService,即会有两个线程池,一个用来从DiskCache获取resource,另一个用来从Source中获取(通常是下载)· 线程的封装单位是EngineJob,有两个顺序状态,先是CacheState,在此状态先进入DiskCacheService中执行获取,如果没找到则进入SourceState,进到SourceService中执行下载6.Glide的Target:负责图片加载的回调。

四、总结以上便是 Glide 的源码和原理,它内部的运作实在是太复杂了,但正是这种复杂的内部实现使得 Glide 的可扩展型得到增强。

比如我们可以自定义磁盘缓存策略,自定义 ModelLoader 以实现 Model 到 Data 的转换,也可以自定义 ResourceDecoder 和 ResourceTranscoder 来实现资源的解码和转码。

用一张图来总结整个加载过程:好啦,文章写到这里就结束了,如果你觉得文章写得不错就给个赞呗!如果你觉得那里值得改进的,请给我留言。

一定会认真查阅,修正不足。

谢谢!更多更详细更专业android架构资料。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/tougao/648315.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-17
下一篇 2022-04-17

发表评论

登录后才能评论

评论列表(0条)

保存