我们经常会涉及到对相机拍照,然后处理拍照后的图片,最后在显示到UI上。如果处理的不好,就会导致系统卡顿,甚至会出现OOM,程序崩溃。
图片的处理
public static BitmapDrawable getScaledDrawable(Activity a, String path) {
if (a == null) return null;
Display display = a.getWindowManager().getDefaultDisplay();
int destWidth = display.getWidth();
int destHeight = display.getHeight();
// Read in the dimensions of the image on disk
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
int srcHeight = options.outHeight;
int srcWidth = options.outWidth;
int inSampleSize = 1;
if (srcHeight > destHeight || srcWidth > destWidth) {
if (srcWidth > srcHeight) {
inSampleSize = Math.round(srcHeight / destHeight);
} else {
inSampleSize = Math.round(srcWidth / destWidth);
}
}
options = new BitmapFactory.Options();
options.inSampleSize = inSampleSize;
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
return new BitmapDrawable(a.getResources(), bitmap);
}
图片的回收
public static void cleanImageView (ImageView imageView) {
if (!(imageView.getDrawable() instanceof BitmapDrawable))
return;
// clean uo the view's image for the sake of memory
BitmapDrawable b = (BitmapDrawable) imageView.getDrawable();
b.getBitmap().recycle();
imageView.setImageDrawable(null);
}
Bitmap.recycle() 方法的调用需要一些解释。Android开发文档暗示不需要调用Bitmap.recycle()方法,但实际上需要。
Bitmap.recycle()方法释放了Bitmap占用的原始存储空间。这也是Bitmap对象最核心的部分,这取决于具体的安卓版本,原始存储空间可大可小,在Honeycomb之前,它存储了Java Bitmap的所有数据。
如果不主动调用recycle()方法释放内存,占用的存储空间也会被清理。但是,它是在将来的某个时间点在finalizer中清理,而不是在Bitmap自身的垃圾回收中清理。这意味着很可能在finalizer调用之前,应用已经耗尽内存资源了。
finalizer的执行有时不太靠谱,且这类bug很难追踪和重现。因此,如果应用使用的图片文件很大,最好主动调用recycle()方法,以避免可能的内存耗尽问题。
在onStart() 方法中加载图片,在onStop()方法中移除图片是一种好的习惯。这些方法标志着用户可以看到Activity的时间点。