图片处理之 -- OOM(解决方法)
作者: 夏至欢迎转载,也请保留这段申明: OOM (Out of Memory)内存溢出,这个是在处理图片的时候,如果没处理好,经常会出现的问题的。为什么呢?因为Android 系统会为每个 App 程序 分配一个独立的工作空间,或者分配一个单独的Dalvik虚拟机,每个程序都能单独运行而不相互干扰。而 Android 的每一个虚拟机都有一个最大的限制,当我们占用的内存超过这个申请的内存,就会报
作者: 夏至
欢迎转载,也请保留这段申明: http://blog.csdn.net/u011418943/article/details/53002793
OOM (Out of Memory)内存溢出,这个是在处理图片的时候,如果没处理好,经常会出现的问题的。为什么呢?因为Android 系统会为每个 App 程序 分配一个独立的工作空间,或者分配一个单独的Dalvik虚拟机,每个程序都能单独运行而不相互干扰。而 Android 的每一个虚拟机都有一个最大的限制,当我们占用的内存超过这个申请的内存,就会报错 OOM 的错误。
常用的有,更换壁纸的时候,预览图没有压缩,直接大图片显示,多张图片一起导致OOM,还有画册也一样。
每台机器给虚拟机分配的内存大小都是不一样的,可以通过这 ActivityManager 来获取最大的内存:
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
Log.d("zsr", "mem: "+activityManager.getMemoryClass());
1、采用低内存占字节编码形式
在我们的 BitmapFacory.Option 中,我们采用的编码方式有两种,一种是 Bitmap.Config.ARGB_8888 和 Bitmap.Config.ARGB_4444 两种:
- Bitmap.Config.ARGB_8888 : 每个像素占8位 ,所以这个模式为 32 位
- Bitmap.Config.ARGB_4444 : 每个像素占4位,所以这个模式为 16位
2、使用图片压缩
同样,在 BitmapFactory.Option 中,我们有 inSampleSize 设置缩放属性,比如写成 inSampleSize = 2,则是缩小一半,这样确实能达到缩小的效果;但是也不能一味的压缩,如果一章图片本来就很小,你再压缩,那么它就会变得很模糊,而且还要考虑图片的伸缩性。
具体代码如下:
private Bitmap scaleBitmap(int id,int scale){
BitmapFactory.Options option = new BitmapFactory.Options();
option.inJustDecodeBounds = true; // 此时decode为null
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), id,option);
Log.d("zsr", "bitmap: "+bitmap);
Log.d("zsr", "tw/th: "+option.outWidth+" / "+option.outHeight);
option.inPreferredConfig = Bitmap.Config.ARGB_4444;
option.inSampleSize = scale;
option.inPurgeable = true; // 允许内存不足的 时候被清除
option.inInputShareable = true; // 与inPurgeable 一起使用才有效
option.inJustDecodeBounds = false; //此时要设置成flase
bitmap = BitmapFactory.decodeResource(getResources(), id,option);
Log.d("zsr", "sw/sh: "+bitmap.getWidth()+" / "+bitmap.getHeight());
return bitmap;
}
可以看到这里用到了 inJustDecodeBounds = true 这个属性,这个时候,系统就不会让它占用内存,所以返回回来的 bitmap 为null,但是我们用 option.outWidth 和 option.outHeight 获取宽和高
压缩一半:
mImageView.setImageBitmap(scaleBitmap(R.drawable.image5, 4));
很模糊,有时候我们无法判断下载过来的图片的大小,有时太大,你压缩得不好,还是占内存,有时太小,又被你压缩得太狠,无法使用,所以我们应该让它自动去判断。所以应该怎么写:
private static int sampleSize(BitmapFactory.Options option,int reWidth,int reHeight){
int width = option.outWidth;
int height = option.outHeight;
int inSampleSize = 1;
if (width > reWidth && height > reHeight) {
int radioWidth = Math.round(width*1.0f/reWidth);
int radioHeight = Math.round(height*1.0f/reHeight);
inSampleSize = Math.max(radioWidth, radioHeight);
}
return inSampleSize;
}
把上面的inSampleSize 改成
option.inSampleSize = sampleSize(option,273,273);
这里的273,273,是在我的 模拟器上看起来不失真且比较清晰的情况,大家可以根据它来修改。
这样,就再也不用担心加载大图片而导致的OOM问题了;
下一章,我们来加载网络下载的图片,然后让它显示,用到Gson解析json数据,LruCache 缓存等,效果如下,敬请期待:
更多推荐
所有评论(0)