標籤:android 圖片 壓縮
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>
list_item.xml:
<?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 };@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的時候,還是會有些卡頓,有這方面解決經驗的可以給我留言討論。
原始碼已上傳到資源中,可到我的資源中下載。