上一篇文章的链接:从零开始撸一个Fresco之硬盘缓存 转载请注明出处 Fresco源代码文档翻译项目请看这里:Fresco源代码翻译项目 这个项目会不断更新想学习Fresco源代码的同学一定不要错过。 Fresco中有个很重要的功能就是gif和Webp动画的实现,今天我就来讲解一下这个模块,顺便撸了个模块demo出来。这是项目的github地址Fresco动画模块,推荐看博客的时候结合项目一起看,项目中绝大部分类都有细致的注释,看起来还是很清晰的。
先来讲讲pool包中的对象池,对象池有什么用?当我们使用一个频繁创建和销毁的对象的时候,为了减少创建和销毁对象所带来的消耗,我们可以维持一个该对象的集合,当不使用的时候将对象放回集合中,使用的时候直接获取引用赋予值。一个典型的对象池就是线程池。在Fresco中由于要频繁地对Bitmap进行操作,所以对Bitmap我们可以使用对象池,此外还有byte数组等。
1.以Bitmap为例要重新使用一个Bitmap,就需要预期的Bitmap与重用的Bitmap使用的内存字节数相同或者重用的大于预期的,只有这样预期的Bitmap才能完整地放入被重用的Bitmap中。所以这里我们用到了SparseArray(稀疏数组)和Bucket(桶,自定义的类,内部使用了LinkedList)。首先SparseArray的下标表示内存的字节数,由于字节数一般跨度比较大所以使用了SparseArray。SparseArray中储存着Bucket,Bucket表示当两个可以被重用的Bitmap字节数相同时,使用LinkedList进行排列储存。下面的图简单的描述了一下这个数据结构。
- 2.上面的这一个Pool是基于Java内存分配,但是我们都知道一个app能使用的内存是有限制的,因为使用new和创建Bitmap的时候使用的内存都是通过dalvik虚拟机在java堆上分配内存的。Android系统设置了一个Java堆的阈值(48M、24M、16M等)当超出之后就会报OOM。而使用jni代码在native heap上面可以申请的内存却是不受限制的(只受整个手机的内存限制)。所以Fresco当然使用了这个方式以提供Byte数组池。具体封装了jni管理的本地内存的类是imagePipline.memory包下的NativeMemoryChunk类。这里的NativeMemoryChunk只替代了1中申请内存的方式,其他方面不变。2.总结:
上面的图是factoryAndProvider包中类的结构示意图,一定要结合项目一起观看。AnimatedDrawable顾名思义就是一个可以显示动画的Drawable。Android的View在设计的时候为了让Drawable能够实现动画,特意实现了Drawable.CallBack接口。这个接口可以让Drwable对View显示的图像进行调度。AnimatedDrawable就是通过这个机制实现动画的。
在administrator.myanimated包下有个MainActivity,用来演示png、jpg、静态webp、动态webp、gif这五种图像的展示。大家在使用的时候记得将自己准备的这个几种文件按命名,放入app的缓存文件夹里。