Android(安卓)BitmapFactory图片压缩处理(大位图二次采样压缩处理)
16lz
2021-01-25
Android实际开发中,在加载大量图片的时候,比如ViewPager、GridView、ListView中,加载了大量的比较大图片就容易出现OOM(内存溢出)的异常,这是因为一个应用的最大内存使用只有16M,超过了这个值,就会出现OOM。所以我们实际开发中,要想避免OOM出现就要对相应的图片进行压缩处理。
本文即使用了BitmapFactory和BitmapFactory.Option这两个类,对图片进行相应的尺寸压缩处理。经测试,成功解决了未压缩图片之前出现的OOM异常。
实现效果图:
本Demo使用的图片大小为2M左右(压缩以前)。
我压缩图片之前:
我这里将压缩的代码注释掉了:
运行结果:
进行压缩处理后的图片:
压缩后图片大小为:
大约为98KB
运行结果:
源代码:
布局文件:
activity_main:
list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
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 };@Overrideprotected 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;}@Overridepublic int getCount() {return items.length;}@Overridepublic Object getItem(int position) {return items[position];}@Overridepublic long getItemId(int position) {return position;}@Overridepublic 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;}}
BitmapCompressTools(压缩工具类):
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 inSampleSizeoptions.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;}}
达到了预期效果,但是写到这里滑动ListView的时候,还是会有些卡顿,有这方面解决经验的可以给我留言讨论。
源代码已上传到资源中,可到我的资源中下载。
更多相关文章
- Android学习笔记之ImageSwitcher
- 项目在android studio 中出现 .9.png问题的解决方案
- Android(安卓)富文本编辑器 图文混排
- Android(安卓)减小安装包的大小、apk瘦身
- 迷途d书童 Android(安卓)如何从系统图库中选择图片
- Android开发心得——网页通过webview调用Android的图片或文件选
- ImageView中图片保存到文件
- mipmap和drawable的区别
- Android(安卓)res下三个drawable文件夹的用途