Android Bitmap资源的简单池化

来源:互联网 发布:银联数据待遇 编辑:程序博客网 时间:2024/04/30 14:56
Android Bitmap资源的简单池化

说一下Bitmap池化的原因: Bitmap在内存中的体现基本就是一大块的内存,当然还有对应的类的数据,
这就造成了Bitmap的create<Bitmap.createBitmap()> 以及在被dalvik GC的时候会付出比较大的时间代价.
池化说白了就是空间换时间<池化本身是一个非常古老的优化概念了>,开辟一个回收池,作为一个中间层,
可以减少真正create和GC的次数.

<1>为了池化Bitmap,直接使用bitmap肯定不行,要在Bitmap外边包一层类PoolBitmap<不是继承,而是组合>,PoolBitmap这个类
既有static的从池中取bitmap的方法,也会作为一个个代表bitmap实例的存在, 有一个getter来获取包装的bitmap实例.

<2>回收池本身一般就直接作为一个static的<反正必须是一个全局性质的>List存在于PoolBitmap内,正好实现了对回收池以及其操作的
外部隔离封装<外界当然不需要知道你的回收池长啥样,唯一关心的是要东西还东西>,处于性能的考虑,回收池不会保存bitmap实例的
强引用<万一出泄露了?万一系统资源紧缺?没弹性>,但是weakReference也不行<hold不住不用的资源>,
那么就只有softReference<能hold住资源,但是呢,在真的内存紧缺时,GC也会干掉它指向的资源>.
因为List一般做的操作就是加入新的到队尾,移除某个位置,所以用LinkedList.
一开始池里面是空的,当然了,也可以load class的时候就填几个进去.
回收池中保存的引用是指向PoolBitamp的引用,方便.

<2>一个static,synchronized的方法来获得给定width/height/config<RGB_565之类的> PoolBitmap实例,
一开始会遍历回收池,注意使用softReference的get判断指向的资源是不是被干掉了,如果被GC了,就顺势将引用从池中remove,
如果没有被GC,那么比较一下width/height/config<注意用equals>来看是不是需要的尺寸,如果是那么就将此PoolBitmap引用
从回收池中挪走<有人用了>,返回之. 如果在池里面没有合适的资源,那么就真正动手Bitmap.createBitmap()了,当然,这个也有可能
返回null<内存不足OutOfMemoryError>,这时候还可以尝试一把,因为可能回收池的资源还能释放腾出些内存,清空List,并Bitmap.recycle()
再试一次,如果还是不行,那么就没辙了,返回null,如果有,那么就返回包裹此bitmap的PoolBitamp实例.
最后关键的一步,这个实例的refCount要+1<初始为0>.

<3>refCount是资源可以被回收到池的关键实现,PoolBitamp会有incRef和decRef,在decRef时,
如果这个PoolBitamp的refcount == 0,那么说明
其目前没有被人使用了,可以放到回收池中<回收池也可以定一个MAX, 超过了直接释放资源>.

<4>采用PoolBitmap的一个最大问题是,使用者必须知道何时incRef/decRef,这样才能实现资源的保险使用和及时回收<java不向C++
有析构函数,并且java的对象本身也在堆中>.
一般来说,只有有新引用指向了这个PoolBitamp实例,都应该incRef,在一个引用不指向实例时,应该decRef,一个谨慎的使用例子:
PoolBitmap p1 = PoolBitmap.createBitmap();
PoolBitmap p2 = p1;
p2.incRef();
XXXXXXXXXXX
p2.decRef();
p2 = null;
p1.decRef();
p1 = null;
在传递引用进函数时,也需要一开始就incRef函数完了decRef<其实可能不需要做,但是谨慎总是没错的>.

<5>incRef/decRef都是synchronized的.

<6>PoolBitmap会实现一些对Bitmap方法的简单转发<gitWidth....>

<7>refCount局限性很强,因此Java VM的GC才没有使用这种方式<java GC博大精深,refcount只能给跪>.


<8>还有一种更方便的池化方式,直接使用Android自带的LRUcache.................

1 0
原创粉丝点击