1.Glide源码分析
2.Androidå©ç¨Glideè·åbitmap
3.工欲善其事必先利其器之Glide解读
4.slide和glide有啥不一样的?
5.面试官:我们来聊聊Glide吧……
Glide源码分析
深入剖析Glide源码:解析与理解其架构与机制
1. Glide三大关键流程
使用Glide加载时,主要包含三大关键流程:with、load、into。通过链式调用这些方法,能轻松完成加载任务,writeandflush 源码但背后蕴含的原理复杂且源码规模庞大。分析源码时,需抓住重点。
1.1 with主线
with方法是Glide中的重要接口,可传入Activity或Fragment,与页面生命周期紧密关联。在分析中,我们曾遇到线上事故,因伙伴在with方法中传入了Context而非Activity,导致页面消失后请求仍在后台运行,最终刷新页面时找不到加载的容器直接崩溃。因此,with方法与页面生命周期息息相关。
1.1.1 Glide创建
通过getRetriever方法最终获得RequestManagerRetriever对象。在Glide的构造方法中,通过双检锁方式创建Glide对象。之后,调用Glide的build方法创建一个Glide实例,传入缓存和Bitmap池等对象。
1.1.2 RequestManagerRetriever
Glide的build方法直接创建RequestManagerRetriever对象,需requestManagerFactory参数,若未定义则默认为DEFAULT_FACTORY。获取此对象后,方便后续加载。考试后台系统源码
1.1.3 生命周期管理
在获取RequestManagerRetriever后,调用其get方法。当with方法传入Activity时,会在子线程调用另一个get方法,而主线程中通过fragmentGet方法,创建空Fragment并同步页面生命周期。
1.1.4 总结
with方法主要完成:创建Glide对象,绑定页面生命周期。
1.2 load主线
通过with方法获得RequetManager,调用load方法创建RequestBuilder对象,将加载类型赋值给model。剩余操作由into方法负责。
1.3 into主线
into方法负责Glide的创建和生命周期绑定。传入ImageView,根据其scaleType属性复制RequestOption。into方法调用buildRequest返回Request,并判断是否能执行请求。执行请求或从缓存获取后回调onResourceReady。
1.3.1 发起请求
创建request后,调用RequetManager的track方法,执行请求并添加到请求队列。判断isPaused状态,决定是否发起网络请求。成功加载或从缓存获取后回调onResourceReady。
1.3.2 三级缓存
通过EngineKey获取资源,从内存、活动缓存和LRUCache中查找。若未获取到,则发起网络请求。追溯系统php源码成功后加入活跃缓存并回调onResourceReady。
1.3.3 onResourceReady
资源加载完成或从缓存获取后,调用SingleRequest的onResourceReady方法。判断是否设置RequestListener,最终调用target的onResourceReady方法,显示。
1.3.4 小结
into方法主要步骤包括:创建加载请求、判断请求执行、从缓存获取资源、网络请求与资源回调。
2. 手写简单Glide框架
实现Glide需理解其特性,特别是生命周期绑定和三级缓存。手写时,着重实现这两点。在load方法中,支持多种资源加载,并使用RequestOption保存请求参数。在into方法中,传入ImageView控件,并在buildTargetRequest方法中判断是否发起网络请求。实现三级缓存逻辑,确保加载效率。使用协程进行线程切换,提高性能。通过简单API加载本地或网络链接,实现Glide功能。
Androidå©ç¨Glideè·åbitmap
æè¿å¨å¼ä¸ä¸ªåè½ï¼å ¶ä¸å«äººå·²ç»å好äºå¾çæ¾ç¤ºï¼æ¯ç¨æurl转æäºStringæ ¼å¼çï¼ä½æ¯æéè¦ä¸ä¸ªbitmapæ ¼å¼æ¥åå¾çä¿åï¼åæ¥æ¥çäºGlideä¹ååç°å¯ä»¥å©ç¨Glideæurlå è½½åºæ¥è·å¾bitmapèµæºã
Glideä¸å è½½ä¹åintoå°ä¸ä¸ªsimpleTarget<Bitmap>éå°±å¯ä»¥å¾å°Bitmapèµæºäºã
工欲善其事必先利其器之Glide解读
加入队列流程
当请求开始,Glide首先将调用流程推进到加入队列阶段,通过调用特定方法启动请求执行。快速中值滤波 源码
请求如何运行?
在加入队列阶段之后,真正的执行发生在请求类的`begin()`方法中。具体到Glide中,这通常指向`SingleRequest`类的`begin()`方法,而该方法的调用来源于请求构造器中的`into`方法。在`into`方法内部,最终触发`SingleRequest.obtain()`,从而生成`SingleRequest`对象。因此,可以明确指出,`begin()`方法的调用是实际请求启动的信号。
队列怎么维护的?
在请求执行中,Glide通过`MainActivity`中的特定代码调用`SupportRequestManagerFragment`,并将`RequestManager`对象绑定到此Fragment。`RequestManager`对象是生命周期管理的核心,它实现了`LifecycleListener`接口,并在创建时将其设置为生命周期回调的一部分。这意味着Glide使用了一个无UI的Fragment与`RequestManager`绑定,使得Fragment的生命周期与`RequestManager`同步。
当`onStart`方法被调用,`RequestManager`会解锁并启动所有运行中的请求。`onStop`方法则暂停当前请求并移至等待队列中,而`onDestory`方法则清除所有队列数据,移除监听,并解除Glide与`RequestManager`的绑定关系。这种机制确保了请求执行的有序性和资源的有效管理。
slide和glide有啥不一样的?
一、表达意思不同1、slip:滑倒,付款成功页面源码失足;溜走,悄悄地走;迅速放置(某物),偷偷塞;(物)滑落,脱落;滑行,打滑;变坏,下降;陷入,进入(困难或不愉快的处境);(飞机飞行中的)侧滑;(地质)滑移,滑距;瘦小的年轻人。
2、slide:(使)滑行,滑动;滑落;迅速熟练地进出;(使)快捷而悄声地移动;(价格等)下滑,下跌;逐渐败坏,开始出现问题;(棒球)滑垒;(吉他)滑奏;无后帮凉鞋(或轻便鞋)。
3、glide:滑行,滑动;滑翔;做事顺利;悄悄地走,流逝;滑音,延音;(尤指向腿侧的)斜击。
二、侧重点不同
1、slip:侧重于不自觉地、偶然地滑动。
2、slide:侧重于指与光滑表面保持接触并且迅速地连续滑动。
3、glide:侧重于自由、顺畅地流动,或者说不费力、无声响地滑动。
例句
1、Robert had slipped her a note in school.
罗伯特上学时偷偷地塞给了她一张字条。
2、She had slid into a depression.
她不知不觉地抑郁寡欢起来。
3、The plane managed to glide down to the runway.
飞机终于成功地滑翔降落在跑道上。
面试官:我们来聊聊Glide吧……
Glide不仅是我们常用的加载框架也是面试中的高频问题,我发现许多工作多年的小伙伴仍然只是停留在使用阶段。我今天想要站在面试者的角度,和大家聊一聊Glide。我希望当大家看完这篇文章后,当面试官问你为什么使用Glide时,你可以给出更深入的回答。
为什么使用Glide呢?面试官可能会问你。首先,Glide使用方便,API简洁,你只需使用with、load、into三步就可以加载。其次,Glide可以自动绑定生命周期,根据绑定的Activity或Fragment生命周期管理请求。此外,Glide还支持多级配置,可以对应用、单独页面(Activity/Fragment)、单个请求进行独立配置。Glide还拥有高效缓存策略,包含两级内存缓存和文件缓存,它支持多种格式,如Gif、WebP、Video,并且可以灵活扩展。
Glide的加载流程大致如下:Glide#with获取与生命周期绑定的RequestManager,RequestManager通过load获取对应的RequestBuilder。根据RequestBuilder构建对应的Request,Target将Request,Target交给RequestManager进行统一管理。调用RequestManager#track开始进行请求。request通过Engine分别尝试从活动缓存、Lru缓存、文件缓存中加载,当以上的缓存中都不存在对应的后,会从网络中获取。而网络获取大致可以分成,ModelLoader模型匹配,DataFetcher数据获取,然后经历解码、变换、转换。如果能够进行缓存原始数据,还会将解码的数据进行编码缓存到文件。
Glide通过给Fragment/Activity插入一个不可见的Fragment,通过监听该Fragment的生命周期来实现对应的请求管理。但如果在Fragment中使用了Activity,而在的请求过程中Fragment被销毁,但是请求并没有结束,这会造成内存泄漏。
Glide的请求参数配置分为三级:第一级作用于Glide,在RequestManger的构造方法通过GlideContext获取进行配置处理;第二级作用于RequestManger,如果要针对某个RequestManger进行配置处理,可以使用RequestManger#ApplyDefaultRequestOptions来更新默认配置;第三级作用于RequestBuilder,通过它的Apply方法为每一个请求的配置进行更新。
Glide的缓存管理分为内存缓存和文件缓存,其中内存缓存又分为活动资源缓存、Lru缓存和文件缓存。文件缓存分为资源缓存和原始数据缓存。内存缓存中,活动资源缓存将正在使用的加入活动资源缓存,每增加一个使用对象,引用计数器加一;Lru缓存按照最近最少使用的原则管理,当缓存满时,优先移除访问时间最久的那个。活动资源缓存以较小的代价维护当前在内存中使用的资源,减轻Lru缓存的压力,提高缓存效率。文件缓存中,资源文件缓存根据当前需要的资源类型和大小等信息进行缓存,获取数据时不需要解码操作,可以直接使用。原始数据是网络加载的数据,需要解码后再缓存。
Glide的内存管理包括防止OOM和内存抖动。防止OOM方面,Glide使用采样、弱引用和生命周期绑定等方式减小加载到内存的大小,及时清除不需要使用的对象引用,降低OOM概率。内存抖动的处理中,Glide使用对象重用池技术,如BitmAppool对Bitmap进行重用,减少内存分配和取消分配,提高性能。
在列表页加载中,由于RecyclerView、ListView的View复用机制,可能出现第一个item的显示在第个上,这是错误的。Glide通过给Target#setRequest关联Target与Request,针对View类型的Target,setRequest实质是给View设置tag,通过tag保存request,当下一个持有相同View的Target到来时,可以取出原来的request并取消。但针对非View类型的target,如果要使用这个特性,需要提供原来的在使用的target,而不是像View一样重新创建一个新的对象。
Glide中的线程和线程池配置对性能有重要影响。关于线程线程池,主要涉及两种情况:加载回调和Glide的线程池配置。加载回调有两种方式:into和submit,into加载的会回调到主线程;submit的回调则在当前线程进行。Glide的线程池配置包括四种类型:DiskCacheExecutor、SourceExecutor、UnlimitedSourceExecutor和AnimationExecutor,它们分别适用于不同场景,如文件加载、网络加载、快速任务处理和动画处理。
Glide如何加载不同类型的资源?Glide通过RequestManager#as方法确定目标需要的资源类型,通过load方法确定需要加载的model资源类型,资源加载过程涉及ModelLoader的模型加载、解码器的解码、转码器的转换,这些过程构建了LoadPath,而每个LoadPath包含多个DecodePath,DecodePath的主要作用是将模型加载的数据解码并转换。Glide会遍历所有可能解析出对应数据的LoadPath,直到数据真正解析成功。
为了深入学习编程基础知识,我推荐以下教学视频:尚学堂的Java集课程,提供从零基础到Java高级技能的学习资源;以及B站上的Python入门课程,适合初学者快速掌握Python编程技能。