在gridview中显示图像时内存不足

时间:2014-04-03 02:47:31

标签: java android

我有一个活动,其中包含一个gridview,用于通过相机或图库显示图像,但我发现它有时会导致OutOfMemory异常,这是代码,我不知道是什么问题

public class WaterPointSubmitActivity extends Activity {

    private final int DIALOG_TYPE_IMAGE = 11;

    private final int Result_Code_Camera = 11;
    private final int Result_Code_Local = 12;

    private final int Dialog_Source_Value_TakePhoto = 0; // the index in the array.xml
    private final int Dialog_Source_value_Local = 1;


    private ArrayList<String> mGridViewImages = new ArrayList<String>();
    private GridView mGridView;

    private ImageAdapter mGridViewAdapter;
    private ImageView mImageAddButton;
    private Uri mPhotoToBeUploadURI;


    private AsyncHttpClient mAsyncHttpClient = Helper.getAsyncHttpClient();
    private RequestHandle mCurrentRequset;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_point_submit);
        this.setupViews();
    }

    private void setupViews() {
        mGridView = (GridView) findViewById(R.id.images_grid_view);
        mGridViewAdapter = new ImageAdapter(this, R.layout.common_expose_image_item, mGridViewImages);
        mGridView.setAdapter(mGridViewAdapter);

        //trigger the image choose dialog
        mImageAddButton = (ImageView) findViewById(R.id.pollution_add_image);
        mImageAddButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showDialog(DIALOG_TYPE_IMAGE);
            }
        });
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        switch (id) {
            case DIALOG_TYPE_IMAGE:
                builder.setTitle(getString(R.string.dialog_choose_photo)).setItems(R.array.point_image_source, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        switch (which) {
                            case Dialog_Source_Value_TakePhoto:
                                //get image by camera
                                mPhotoToBeUploadURI = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
                                Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                                cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoToBeUploadURI);

                                startActivityForResult(cameraIntent, Result_Code_Camera);
                                break;
                            case Dialog_Source_value_Local:
                                //from gallery 
                                Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
                                photoPickerIntent.setType("image/*");
                                startActivityForResult(photoPickerIntent, Result_Code_Local);
                                break;
                        }
                    }
                });
                Dialog target = builder.create();
                target.setCanceledOnTouchOutside(false);
                return target;
        }
        return null;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
        if (resultCode == RESULT_OK) {
            String imageFile = null;
            switch (requestCode) {
                case Result_Code_Camera:
                    String[] projection = {
                            MediaStore.MediaColumns._ID,
                            MediaStore.Images.ImageColumns.ORIENTATION,
                            MediaStore.Images.Media.DATA
                    };
                    Cursor c = getContentResolver().query(mPhotoToBeUploadURI, projection, null, null, null);
                    c.moveToFirst();
                    imageFile = c.getString(c.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
                    break;
                case Result_Code_Local:
                    Uri selectedImage = imageReturnedIntent.getData();
                    String[] filePathColumn = {MediaStore.Images.Media.DATA};

                    Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
                    cursor.moveToFirst();

                    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                    imageFile = cursor.getString(columnIndex);
                    cursor.close();
                    break;
            }
            mGridViewImages.add(imageFile);
            mGridViewAdapter.notifyDataSetChanged();
        }
    }

    class ImageAdapter extends ArrayAdapter<String> {
        private int mResourceId;

        public ImageAdapter(Context context, int resource, List<String> items) {
            super(context, resource, items);
            mResourceId = resource;
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;

            if (convertView == null || convertView.getTag() == null) {
                convertView = getLayoutInflater().inflate(mResourceId, parent, false);

                holder = new ViewHolder();
                holder.pointImage = (ImageView) convertView.findViewById(R.id.pollution_image);
                holder.pointDeleteImage = convertView.findViewById(R.id.pollution_image_delete);
                convertView.setTag(holder);
                holder.pointDeleteImage.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        deleteImage(position);
                    }
                });
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            String filePath = getItem(position);
            if (filePath != null) {
                Bitmap bitmap = BitmapFactory.decodeFile(filePath);
                holder.pointImage.setImageBitmap(bitmap);
            }
            return convertView;
        }
    }

    private void deleteImage(int position) {
        mGridViewImages.remove(position);
        mGridViewAdapter.notifyDataSetChanged();
    }

    static class ViewHolder {
        ImageView pointImage;
        View pointDeleteImage;
    }
}

有什么问题?

2 个答案:

答案 0 :(得分:0)

您的视图正在加载完整大小的位图,导致OOM使用BitmapFactory选项在将位图加载到内存之前缩放位图

BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds = true;
                    BitmapFactory.decodeFile(selectedImagePath, options);
                    int imageHeight = options.outHeight;
                    int imageWidth = options.outWidth;
                    String imageType = options.outMimeType;

                        options.inSampleSize = calculateInSampleSize(options,320,480);


                    options.inJustDecodeBounds = false;
                    Bitmap photo = BitmapFactory.decodeFile(selectedImagePath,options);

帮手方法

public int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
    }

答案 1 :(得分:0)

您只需将此行添加到清单文件中....它将为您的应用程序分配大内存..

android:largeHeap="true"