说到图片加载框架,第一个想到的自然就是Glide,但是你真的了解它吗?如果面试问到相关问题你能顺利答出来吗?
- 还清楚其他的图片加载框架吗?各自有什么优缺点?
- 图片三级缓存可以说下吗?
- 一个图片加载框架会涉及到哪些重要的知识?
还清楚其他的图片加载框架吗?各自有什么优缺点?
Glide:
- 多种图片格式的缓存,适用于更多的
内容表现形式
(如Gif、WebP、缩略图、Video) - 生命周期集成(根据Activity或者Fragment的
生命周期管理
图片加载请求) - 高效处理Bitmap(bitmap的
复用和主动回收
,减少系统回收压力) - 高效的缓存策略,灵活(Picasso只会缓存原始尺寸的图片,Glide缓存的是多种规格),
加载速度快且内存开销小
(默认Bitmap格式的不同,使得内存开销是Picasso的一半)
Fresco:
- 最大的优势在于5.0以下(最低2.3)的bitmap加载。在5.0以下系统,Fresco将图片放到一个特别的
内存区域
(Ashmem区) - 大大减少
OOM
(在更底层的Native层对OOM进行处理,图片将不再占用App的内存) - 适用于需要
高性能加载大量图片
的场景
图片三级缓存可以说下吗?
三级缓存:内存缓存,硬盘缓存,网络
- 内存缓存一般是使用
LruCache
,采用最近最少使用算法,设定一个缓存大小,当缓存到达这个大小之后,会将最老的数据移除,保证内存的充足,从而避免oom。 - 硬盘缓存,一般用
DiskLruCache
,思路差不多,也是没次往硬盘写文件,大小超过阀值,就将旧文件删除。 - 网络,即从
网络
获取图片数据,并加载
首次加载数据,通过网络获取图片对象,保存到内存和硬盘中,下次读取数据,会先从内存获取,没有的话就从本地硬盘加载,都没有的话就从网络获取资源。
一个图片加载框架会涉及到哪些重要的知识?
- 线程池 包括网络加载的线程池,加载内存和硬盘缓存的线程池,还有动画线程池,其中对于线程切换还是用的
Handler
class EngineJob<R> implements DecodeJob.Callback<R>,Poolable {
private static final EngineResourceFactory DEFAULT_FACTORY = new EngineResourceFactory();
//创建Handler
private static final Handler MAIN_THREAD_HANDLER =
new Handler(Looper.getMainLooper(), new MainThreadCallback());
缓存 就是刚才上面说到的三级缓存,用于缓存图片
防止oom 1)缓存处理,比如
LruCache
中缓存大小的设置 2)软引用,缓存中尽量存储软引用
,当内存不足时会自动被GC 3)bitmap像素数据存储,ndroid3.0到8.0之间Bitmap像素数据存在Java堆
,而8.0之后像素数据存到native堆
中onLowMemory 当内存不足时,会回调
onLowMemory
方法,可以在里面进行一些内存的释放内存泄漏 ImageView内存泄漏,在界面被
销毁
的时候要记得取消图片加载任务,否则可能会导致内存泄漏图片错乱 因为recycleview的
复用机制
,可能会导致图片错乱,这时候就要根据图片的tag来判断图片加载地址是否正确。
参考链接
https://juejin.im/post/6844903986412126216