1. 内存管理基础知识
http://www.cnblogs.com/xingfuzzhd/p/3485924.html
- 1.
mImageView.setImageResource(R.drawable.my_image);
这段代码会调用 BitmapFactory.decodeStream() 生成一个 Bitmap。所以不要以为它比自己创建 Bitmap 节省内存。
3. 实际测试:
我使用了多种调用图片的方法来测试:
第一种:
// 直接载入资源 id
ImageView image = (ImageView) findViewById(R.id.imageView1)
第二种:
创建一个函数,根据 id 载入图片。杀死 Activity 时回收 Bitmap
public BitmapDrawable getImageBitmap(int idImage) { Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), idImage); images.add(bitmap); return new BitmapDrawable(context.getResources(), bitmap); }
第三种:
创建一个类
/** * solution for OOM ------> compress bitmap */ public class BitmapUtils { private static final String TAG = "BitmapUtils"; /** * calulate the compress rate */ private static int calculateInSampleSize(BitmapFactory.Options opts,int reqHeight,int reqWidth) { if(opts == null) { return -1; } int width = opts.outWidth; int height = opts.outHeight; int sampleSize = 1; if(width > reqWidth || height > reqHeight) { int heightRatio = (int) (height/(float)reqHeight); int widthRatio = (int) (width/(float)reqWidth); sampleSize = (heightRatio > widthRatio) ? widthRatio : heightRatio; } return sampleSize; } /** * compress an image refer to the goal dimension * @param res * @param resId * @param reqWidth * @param reqHeight * @return Bitmap */ public static Bitmap decodeSampledBitmapFromResource(Resources res,int resId,int reqWidth,int reqHeight) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, opts); int sampleSize = calculateInSampleSize(opts, reqHeight, reqWidth); Log.i(TAG,"before[width:"+opts.outWidth+",height:"+opts.outHeight+"]"); opts.inJustDecodeBounds = false; opts.inSampleSize = sampleSize; /* newly added */ opts.inPreferredConfig = Bitmap.Config.RGB_565; opts.inPurgeable = true; opts.inInputShareable = true; /* newly added */ Log.i(TAG,"insamplesize="+sampleSize); Bitmap bitmap = BitmapFactory.decodeResource(res, resId, opts); Log.i(TAG,"after[width:"+bitmap.getWidth()+",height:"+bitmap.getHeight()+"]"); return bitmap; } /** * compress an image refer to the goal dimension * * @param data image byte array * @param reqWidth * @param reqHeight * @return */ public static Bitmap decodeSampledBitmapFromByteArray(byte[] data,int reqWidth,int reqHeight) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(data, 0, data.length, opts); Log.i(TAG,"before[width:"+opts.outWidth+",height:"+opts.outHeight+"]"); opts.inSampleSize = calculateInSampleSize(opts, reqHeight, reqWidth); Log.i(TAG,"insamplesize="+opts.inSampleSize); opts.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts); Log.i(TAG,"after[width:"+bitmap.getWidth()+",height:"+bitmap.getHeight()+"]"); return bitmap; } public static Bitmap decodeResourceWithLowMemory(Context context, int resId) { BitmapFactory.Options opt = new BitmapFactory.Options(); // Bitmap.Config.ALPHA_8,Bitmap.Config.ARGB_4444,Bitmap.Config.RGB_565 // 设置这几个参数效果都差不多,确实相当省内存啊,而且还跟原图清晰度相当 opt.inPreferredConfig = Bitmap.Config.RGB_565; opt.inPurgeable = true; opt.inInputShareable = true; return BitmapFactory.decodeResource(context.getResources(), resId, opt); } public static Bitmap loadToImageViewFromResource(Resources res,int resId,ImageView imageView) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, opts); int reqHeight = imageView.getLayoutParams().height; int reqWidth = imageView.getLayoutParams().width; int sampleSize = calculateInSampleSize(opts, reqHeight, reqWidth); Log.i(TAG,"before[width:"+opts.outWidth+",height:"+opts.outHeight+"]"); opts.inJustDecodeBounds = false; opts.inSampleSize = sampleSize; /* newly added */ opts.inPreferredConfig = Bitmap.Config.RGB_565; opts.inPurgeable = true; opts.inInputShareable = true; /* newly added */ Log.i(TAG,"insamplesize="+sampleSize); Bitmap bitmap = BitmapFactory.decodeResource(res, resId, opts); Log.i(TAG,"after[width:"+bitmap.getWidth()+",height:"+bitmap.getHeight()+"]"); return bitmap; } }
4. 测试过程:
创建两个 Activity,每个都载入几个大图片,然后两个 Activity 之间不停的切换。
第一种方法,切换多次后 OOM (out of memory)。 第二种方法,更快的 OOM。
第三种,如果压缩率够高的话,几乎不会 OOM。比如原始图片为 2048 * 1600,然后目标 ImageView 的大小为 200* 150。最后内存消耗将大大减小。然后如果
两者分辨率差距不大,最后内存消耗将不会被优化,最后也将 OOM。