1、适当调整图像大小,因为手机屏幕尺寸有限,分配给图像的显示区域有限,尤其对于超大 图片,加载自网络或者SD卡,图片文件的体积达到几m或者十几m的图片,需要在加载内存前进行以下适当处理。
加载到内存前,先计算该bitmap的大小,然后适当调节采样率使得加载的图片刚好或稍大于view。
BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; //获取该图片文件的属性,并不是真正把图片加载到内存,而是获取宽高,可以通过宽*高*4获得图片大小 BitmapFactory.decodeFile(imgFile,options); // 计算取样大小,其中minSideLength为最小边的大小, maxNumOfPixels最大像素 options.inSampleSize = computeSampleSize(options,minSideLength, maxNumOfPixels); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(imgFile, options);
public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) { int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels); int roundedSize; if (initialSize <= 8) { roundedSize = 1; while (roundedSize < initialSize) { roundedSize <<= 1; } } else { roundedSize = (initialSize + 7) / 8 * 8; } return roundedSize; } private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) { double w = options.outWidth; double h = options.outHeight; int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math .sqrt(w * h / maxNumOfPixels)); int upperBound = (minSideLength == -1) ? 128 : (int) Math.min( Math.floor(w / minSideLength), Math.floor(h / minSideLength)); if (upperBound < lowerBound) { // return the larger one when there is no overlapping zone. return lowerBound; } if ((maxNumOfPixels == -1) && (minSideLength == -1)) { return 1; } else if (minSideLength == -1) { return lowerBound; } else { return upperBound; } }
2、在listview或gallery等控件中一次性加载大量图片时,只加载屏幕显示的资源,尚未显示的不加载,移除屏幕的资源及时释放,可以采用强引用+弱引用的2级
缓存方式,提高加载性能;
3、缓存图像到内存,采用软引用缓存到内存,而不是在每次使用的时候都重新加载到内存
4、采用低内存占用量的编码方式,比如bitmap.config.argb_4444比8888省内存
5、谨慎使用static引用对象,例如:
public class ClassName{
private static Context mContext;
}
如果将activity赋值到mContext,即使activity已经ondestroy,但由于仍有对象引用它,因此activity仍然不会释放
6、自定义对内存分配大小,优化delvik虚拟机的对内存分配