Android实际开发中,在加载大量图片的时候,比如ViewPager、GridView、ListView中,加载了大量的比较大图片就容易出现OOM(内存溢出)的异常,这是因为一个应用的最大内存使用只有16M,超过了这个值,就会出现OOM。所以我们实际开发中,要想避免OOM出现就要对相应的图片进行压缩处理。
本文即使用了BitmapFactory和BitmapFactory.Option这两个类,对图片进行相应的尺寸压缩处理。经测试,成功解决了未压缩图片之前出现的OOM异常。
实现效果图:
本Demo使用的图片大小为2M左右(压缩以前)。
我压缩图片之前:
我这里将压缩的代码注释掉了:
运行结果:
进行压缩处理后的图片:
压缩后图片大小为:
大约为98KB
运行结果:
源代码:
布局文件:
activity_main:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" > </ListView> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp"/> </LinearLayout>
MainActivity:
package com.android_bitmapcompressdemo; import android.app.Activity; import android.os.Bundle; import android.widget.ListView; public class MainActivity extends Activity { private ListView listView; private MyAdapter adapter; private int[] items = new int[] { R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView); adapter = new MyAdapter(this, items); listView.setAdapter(adapter); adapter.notifyDataSetChanged(); } }
ListView适配器:MyAdapter:
package com.android_bitmapcompressdemo; import android.content.Context; import android.graphics.Bitmap; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class MyAdapter extends BaseAdapter { private int[] items = new int[] {}; private Context context; private String TAG = "zhongyao"; private Bitmap bitmap = null; public MyAdapter(Context context, int[] items) { this.context = context; this.items = items; } @Override public int getCount() { return items.length; } @Override public Object getItem(int position) { return items[position]; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.list_item, null); holder = new ViewHolder(); holder.imageView = (ImageView) convertView.findViewById(R.id.imageView); holder.textView = (TextView) convertView.findViewById(R.id.textView); convertView.setTag(holder); }else { holder = (ViewHolder) convertView.getTag(); } bitmap = BitmapCompressTools.decodeSampledBitmapFromResource( context.getResources(), R.drawable.pc, 100, 100); Log.d(TAG, "压缩之后的图片大小为:" + bitmap.getByteCount()); holder.imageView.setImageBitmap(bitmap); holder.textView.setText("图片"+position); return convertView; } class ViewHolder { ImageView imageView; TextView textView; } }
package com.android_bitmapcompressdemo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; public class BitmapCompressTools { public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // 给定的BitmapFactory设置解码的参数 final BitmapFactory.Options options = new BitmapFactory.Options(); // 从解码器中获取原始图片的宽高,这样避免了直接申请内存空间 options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 压缩完后便可以将inJustDecodeBounds设置为false了。 options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); } /** * 指定图片的缩放比例 * * @param options * @param reqWidth * @param reqHeight * @return */ 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 halfHeight = height / 2; // // final int halfWidth = width / 2; // // while ((halfHeight / inSampleSize) > reqHeight // // && (halfWidth / inSampleSize) > reqWidth) { // // inSampleSize *= 2; // // } // /** * 压缩方式一 */ // 计算压缩的比例:分为宽高比例 final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; // } return inSampleSize; } }
源代码已上传到资源中,可到我的资源中下载。