Android的加载大图片引起内存问题之OOM异常

来源:互联网 发布:淘宝买家怎么发微淘 编辑:程序博客网 时间:2024/04/28 13:00

大图片所引起的内存问题(oom):

在我们android开发中,一个应用使用的内存大小是有限制的.在应用中,如果大量的使用bitmap就很可能导致内存溢出的问题。比如我在曾经的一个项目中遇到的问题:要使用Gallery来显示多张不同的图片,在给Gallery的每个Item设置图片的时候,想到Bitmap如果不手动的recycle,系统是不会回收它所在的资源的,因为android为了提高效率,bitmap真正的位图数据是在ndk中用C写的,所以就直接使用setImageResource(iconResId),但是部分配置较低的设备上还是会出现oom的错误。

先来分析我遇到的这个问题,在setImageResource中,是根据iconResId得到drawable,然后再将drawable显示在view中。我们知道,android对于直接通过资源id载入的资源做了缓存cache,这样下次再需要资源时直接从缓存中得到即可,在Gallery中用到了多个大图片,每个图片都会进行缓存,即使在Gallery中该view被回收了。就是这个地方导致了内存溢出。

对于内存溢出的问题,我一般会从五个方面进行入手:

一是在内存引用上做些处理,比如说使用软引用,强化引用,弱引用

二是可以在内存中加载图片的时候直接在内存中做处理,比如:边界的压缩

三是动态的回收内存

四是优化Dalvik虚拟机的堆内存的分配

五是自定义堆内存大小

而对于前面我们找到的问题,我们对第一个和第二个解决办法进行整合就能够解决这个问题,(写代码):

private static LinkedHashMap<String, Bitmap> hardManager;  

private static ConcurrentHashMap<String, SoftReference<Bitmap>> softManager;  

设置上面两个变量,分别保存包名到Bitmap的强引用的映射和软引用的映射。

在通过包名获取bitmap时,首先在hardManager中判断是否包含该包名,如果有,直接取出;如果没有,则在softManager中判断,有则取出,没有就通过下面方法获取,

private static Bitmap readBitMap(Context context,int resId) {  

1         BitmapFactory.Options opt = new BitmapFactory.Options();  

2         opt.inPreferredConfig = Bitmap.Config.RGB_565;  

3         opt.inPurgeable = true;  

4         opt.inInputShareable = true;  

5         // 获取资源<strong>图片</strong>  

6         InputStream is = context.getResources().openRawResource(resId);  

7         return BitmapFactory.decodeStream(is,null, opt);  

8  }  

获取之后插入到hardManager中,在插入时,做判断只保证hardManager的容量为10,如果大于10,就将最早插入的删除,这样就保证了我们使用大图片时不会造成内存溢出这个问题。

 

0 0
原创粉丝点击