皮皮网

【郭天祥程序源码】【reactnative 项目源码】【更改android 源码】glide 源码解析

来源:端游商业源码 时间:2024-11-23 05:38:38

1.面试官:Glide 是码解如何加载 GIF 动的?
2.字节一面面试题解析:Glide内存优化!
3.Glide源码分析
4.源码解析,码解Glide加载GIF图的码解原理竟然这么简单

glide 源码解析

面试官:Glide 是如何加载 GIF 动的?

       前言

       最近,在一个群里看到有人说面试遇到问题,码解即“Glide 如何加载 GIF 动图?”。码解通常,码解郭天祥程序源码这样的码解细节问题在面试中确实令人印象深刻。

       区分类型

       使用 Glide 加载静态图和 GIF 动图原理不同。码解在加载之前,码解需要先区分类型。码解在 Glide 的码解执行流程源码解析中,我们知道网络请求拿到 InputStream 后会执行解码操作。码解此操作涉及 DecodePath#decode() 方法。码解

       解码器的码解选择

       在 decode() 方法中,进一步调用了 decodeResource 方法。码解在这一过程中,Glide 会遍历 decoders 集合,寻找合适的资源解码器进行解码。这个集合可能包含 ByteBufferGifDecoder、ByteBufferBitmapDecoder 和 VideoDecoder 等解码器。当解码成功后,result 不为空,解码流程完成。

       GIF 的识别

       在寻找合适的解码器时,Glide 使用 ImageType 枚举来识别类型。reactnative 项目源码ImageHeaderParserUtils#getType() 方法通过读取流中的前 3 个字节来判断格式。若为 GIF 文件头,则返回类型为 GIF。这样,Glide 就能准确识别出是否为 GIF 动图。

       GIF 加载原理

       找到合适的资源解码器后,即 ByteBufferGifDecoder,接下来就是解码 GIF 动图。在 DecodePath#decodeResourceWithList() 方法中,Glide 调用了 ByteBufferGifDecoder#decode() 方法。在这个方法中,Glide 创建了一个 StandardGifDecoder 实例,用于读取 GIF 图像源的帧数据,并将其解码为单独的帧,用于动画播放。

       GifDrawable 实现动画播放

       StandardGifDecoder 创建了一个 GifDrawable 实例,它是一个实现了 Animatable 接口的 Drawable。GifDrawable 能够播放 GIF 动图。在创建 GifDrawable 时,还创建了 GifFrameLoader 的实例,用于帮助 GifDrawable 实现动画播放的调度。GifFrameLoader 的构造函数中创建了一个主线程的 Handler,这在动画播放中起到了关键作用。

       动画播放流程

       GifDrawable 的更改android 源码 start 方法用于开始播放动画。调用此方法后,动画开始播放。在加载 GIF 动图时,最终在 ImageViewTarget#onResourceReady() 方法中调用 GifDrawable 的 start 方法。接着,GifDrawable#start() 方法中的 startRunning 方法判断 GIF 是否仅有一帧,如果有多个帧,则调用 GifFrameLoader 的 subscribe 方法进行订阅,并调用绘制方法。

       动画帧的加载与绘制

       GifFrameLoader 的 subscribe 方法负责订阅 GIF 动图的帧数据。调用 loadNextFrame 方法后,动画帧开始加载。当收到新帧时,GifDrawable#onFrameReady() 方法被调用,执行绘制操作,使用当前帧的 Bitmap 和 Canvas 将其绘制到 ImageView 上。这样,GifDrawable 循环绘制每一帧的 Bitmap,从而实现了 GIF 动图的连续播放。

       总结

       面试官询问 Glide 如何加载 GIF 动图时,可以简洁明了地回答:Glide 首先通过获取前三个字节判断类型是否为 GIF。确认为 GIF 后,调用合适的解码器(ByteBufferGifDecoder)进行解码,将 GIF 动图转换为单独的跟读app源码帧。通过 GifDrawable 实现动画播放功能,并利用 GifFrameLoader 和 Handler 实现帧的连续绘制和播放,最终在 ImageView 上呈现出 GIF 动图的效果。

字节一面面试题解析:Glide内存优化!

       当处理大量加载时,Glide在RecyclerView中的应用可能会引发内存溢出问题。解决这一问题的关键在于深入理解Glide的内存优化策略,尤其是TrimMemory和LowMemory机制。以下是对这些问题的详细解析:

       1.1 遇到内存溢出的常见场景

       在使用Glide加载大量至RecyclerView时,由于缓存策略,如果不进行适当的管理,可能会导致内存占用过高,引发内存溢出。为了防止这种情况,我们需要采取有效的优化措施。

       2.1 TrimMemory和LowMemory方法的作用

       TrimMemory和LowMemory是Android系统提供的两个内存管理接口,当系统内存紧张时,应用需要响应这些回调,释放一部分缓存资源。TrimMemory主要用于告知应用当前系统的内存状态,如内存不足,而LowMemory则更严重,意味着系统内存严重不足。

       2.2 TrimMemory和LowMemory源码分析

       深入源码可以发现,openfire源码缓存Glide会在接收到TrimMemory或LowMemory回调时,检查自身的内存占用情况,并根据策略调整缓存。这包括清除过期或不再需要的,以释放内存空间。

       2.3 Glide低内存优化操作

       为了应对内存低的情况,Glide提供了以下优化操作:一是配置合适的缓存策略,例如使用LRU(最近最少使用)算法来管理缓存,确保只保留最常使用的;二是监听系统内存变化,当接收到TrimMemory或LowMemory回调时,主动清理缓存;三是考虑使用Bitmap Pool,减少Bitmap的创建和销毁,从而节省内存。

Glide源码分析

       深入剖析Glide源码:解析与理解其架构与机制

       1. Glide三大关键流程

       使用Glide加载时,主要包含三大关键流程:with、load、into。通过链式调用这些方法,能轻松完成加载任务,但背后蕴含的原理复杂且源码规模庞大。分析源码时,需抓住重点。

       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中查找。若未获取到,则发起网络请求。成功后加入活跃缓存并回调onResourceReady。

       1.3.3 onResourceReady

       资源加载完成或从缓存获取后,调用SingleRequest的onResourceReady方法。判断是否设置RequestListener,最终调用target的onResourceReady方法,显示。

       1.3.4 小结

       into方法主要步骤包括:创建加载请求、判断请求执行、从缓存获取资源、网络请求与资源回调。

       2. 手写简单Glide框架

       实现Glide需理解其特性,特别是生命周期绑定和三级缓存。手写时,着重实现这两点。在load方法中,支持多种资源加载,并使用RequestOption保存请求参数。在into方法中,传入ImageView控件,并在buildTargetRequest方法中判断是否发起网络请求。实现三级缓存逻辑,确保加载效率。使用协程进行线程切换,提高性能。通过简单API加载本地或网络链接,实现Glide功能。

源码解析,Glide加载GIF图的原理竟然这么简单

       在探讨之前,让我们明确一点:Android的ImageView实际上并不支持直接加载GIF动图,因为ImageView基于Canvas绘制,而Canvas仅支持drawBitmap一次绘制一张。那么,Glide是如何巧妙地让ImageView展现出GIF动画的呢?

       让我们从Glide的源码入手,今天的主角是GifDrawable。这个类虽然有大约行代码,但理解其工作原理并非无迹可寻。首先,我们注意到一个开始播放第一帧的方法,这可能是入口点。

       代码结构中,当GIF有多帧时,会订阅特定事件。关键在于观察三句代码:一是递增帧位置,表明采用无限轮播算法;二是加载资源回调,通过Target接口来触发;三是消息传递,用Handler进行控制。

       在加载资源的回调中,我们看到消息机制在发挥作用。当接收到消息,会根据what参数进行处理。在handleMessage中,处理了延迟消息和清理消息。延迟消息会获取新帧数据并绘制到ImageView,同时清除旧帧,接着进入下一个帧的加载和清除过程。

       总结来说,Glide加载GIF的原理相当直观:GIF被解析为一系列,通过无限轮播,每次新帧的加载都触发一次请求。在完成绘制后,旧帧会被清除,然后继续下一轮的加载。整个过程通过Handler的消息传递机制驱动循环播放。以上内容摘自Android轮子哥的分享。