1、在APP加载图片时如果在layout文件使用android:src=”@drawable/image”方式设置背景,在加载大图片时会出现内存泄漏的情况(即OOM),以下方法在Activity中设置背景图可以对图片进行有效的压缩。
2、使用bitmap方法对图片进行压缩后,跳转页面,Android虚拟机并未调用bitmap1.recycle()方法对垃圾进行回收,同时还有可能报错,提示bitmap.recycle()已经进行,不能再次执行。此时,由于页面没有被销毁,反复跳转页面还是会出现OOM,因此要根据Activity生命周期在其中调用finish()方法对页面进行销毁,页面垃圾会被自动回收,降低内存消耗。
package utils;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.view.View;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by lenovo on 2017/3/20.
*/
public class BitmapUtils {
/*该方法将图片按宽高像素进行压缩,然后将压缩后的图片放大显示在APP界面中,如果像素设定过小,现示的图片会失真。*/
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
BitmapFactory.decodeResource(res, resId, options);
// 调用上面定义的方法计算inSampleSize值
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 使用获取到的inSampleSize值再次解析图片
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// 源图片的高度和宽度
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// 计算出实际宽高和目标宽高的比率
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
// 一定都会大于等于目标的宽和高。
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
/*该方法以IO流的方式读取图片,将图片设置为背景图*/
public static BitmapDrawable setBackgroundImage(Context context, int resId){
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
//获取资源图片
InputStream is =context.getResources().openRawResource(resId);
Bitmap bitmap = BitmapFactory.decodeStream(is,null, opt);
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return new BitmapDrawable(context.getResources(),bitmap);
}
public static void setAndRecycleBackground(View v, int resID) {
// 获得ImageView当前显示的图片
Bitmap bitmap1 = null;
if (v.getBackground() != null) {
try {
//若是可转成bitmap的背景,手动回收
bitmap1 = ((BitmapDrawable) v.getBackground()).getBitmap();
} catch (ClassCastException e) {
//若无法转成bitmap,则解除引用,确保能被系统GC回收
v.getBackground().setCallback(null);
}
}
// 根据原始位图和Matrix创建新的图片
v.setBackgroundResource(resID);
// bitmap1确认即将不再使用,强制回收,这也是我们经常忽略的地方
if (bitmap1 != null && !bitmap1.isRecycled()) {
bitmap1.recycle();
}
}
public static void releaseViewResouce(View view) {
if (view== null) return;
Drawable drawable = (BitmapDrawable)view.getBackground();
if (drawable != null && drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
}
}
}
}