在Android中的列表视图中显示和滚动大位图时出现异常

时间:2012-02-27 13:39:11

标签: android android-imageview

我正面临这个问题,但无法解决。我的问题是这样的:

  • 我有一个列表视图。我的列表行包含图像视图和一个文本视图
  • 我的SD卡中存有12个大小的20张图像
  • 我必须在列表视图的imageView中设置这些图像

我可以通过以下代码来完成。我在自定义适配器的getView方法中执行此操作:

public View getView (int position, View convertView, ViewGroup parent) {
    //other stuffs like recycling, view holder etc...
    BitmapFactory.Options opt = new BitmapFactory.Options();
    opt.inSampleSize = 4; // tried with 8,12 too
    Bitmap bitmap = BitmapFactory.decodeFile(imageUri, opt);
    holder.imageView.setImageBitmap(bitmap);
    return convertView;
}

现在这个代码可以很好地处理小图像,但对大尺寸图像会造成严重破坏。应用程序与OutOfMemoryError崩溃。如果我尝试将inSampleSize增加到8或12,它会起作用,但图像质量会大幅降低,图像看起来根本不会显示原始图像。我尝试使用imageView.setImageURI(imageUri),但文档建议仅使用setImageBitmap

现在请有人帮我纠正这个问题。如何在不影响图像质量的情况下解决此问题?

4 个答案:

答案 0 :(得分:1)

快速创可能可能有助于使用:

opt.inPreferredConfig = Bitmap.Config.RGB_565;

这将加载没有Alpha通道的图像,并且每个像素仅使用2个字节(而不是使用默认ARGB_8888的4个字节)。

根据列表的长度,您可能需要加载/卸载图像,因为它们在屏幕上显示/离开屏幕。

答案 1 :(得分:1)

尝试将inSampleSize设置为2或4,并使用Matrix类缩放宽度和高度。 但正如你在另一个答案中所说,这可能会影响表现。

float desiredWidth = 60; // the width you want your icon/image to be
float scale = desiredWidth/actualWidth // bitmap.getWidth() for actualWidth
// float scale = desiredHeight/actualHeight // If you want to go by a particular height

Matrix matrix = new Matrix();
matrix.setScale(scale, scale);

holder.imageView.setImageBitmap(Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false));
bitmap.recycle(); // ish

第二个选项。在实例化Adapter类之前,获取缩略图像的Cursor对象,并将光标传递给适配器的构造函数,使其成为可变类。在ListView中的每个视图行使用相同的光标。

Uri tUri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI; // Where thumbnails are stored
String[] columns = { MediaStore.Images.ImageColumns._ID,  MediaStore.Images.ImageColumns.DATE_TAKEN, MediaStore.Images.ImageColumns.DISPLAY_NAME};

Cursor thumbCursor = this.managedQuery(tUri, null, null, null, null); // May want to use more paramaters to filter results
cursor.moveToFirst();

.... instantiate adapter, pass in cursor ....

public View getView (int position, View convertView, ViewGroup parent) {

int columnIndex = cursor.getColumnIndex(MediaStore.Images.Thumbnails.DATA);
String filePath = cursor.getString(columnIndex);
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
holder.imageView.setImageBitmap(bitmap);
cur.moveToNext();
// BitmapDrawable d = new BitmapDrawable(listActivity.getResources(), filePath);
// holder.imageView.setImageDrawable(d);
}

这样的事情。我匆忙做了。祝你好运=)

答案 2 :(得分:0)

尝试根据图像尺寸计算比例因子,并调用Bitmap.recycle()以释放已分配的内存

答案 3 :(得分:0)

首先,由于图像是12mb(即使它们只有1mb),你必须缩放它们并缩小它们到你的{的尺寸{1}}。

虽然您也可以查看imageview ...

outofmemory exception

我也假设,您正在public View getView (int position, View convertView, ViewGroup parent) { //other stuffs like recycling, view holder etc... boolean OOME = true; int sample = 4; while(OOME) { try { BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inSampleSize = sample; // tried with 8,12 too Bitmap bitmap = BitmapFactory.decodeFile(imageUri, opt); bitmap = bitmap.createScaledBitmap(bitmap,newWidth,newHeight,true); holder.imageView.setImageBitmap(bitmap); OOME = false; } catch(OutOfMemoryError e) { sample *= 2; } } return convertView; } 中执行所有解码内容,以使background thread顺利...

虽然listview scrollBitmaps存在很多问题,但这是我可以提供的最佳方法......我仍然愿意接受任何更改修改增强 ...