大图片所引起的内存问题(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,就将最早插入的删除,这样就保证了我们使用大图片时不会造成内存溢出这个问题。

猜你喜欢

转载自www.cnblogs.com/hpisfox/p/9071984.html
今日推荐