[英]Exception while displaying and scrolling large bitmaps in list view in Android
I am facing this issue but unable to resolve. 我正面临这个问题,但无法解决。 My problem goes like this:
我的问题是这样的:
I am able to do it by following code. 我可以通过以下代码来完成它。 This I am doing in
getView
method of my custom adapter: 这是我在我的自定义适配器的
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;
}
Now this code works fine with small images but plays havoc for image of large size. 现在这个代码可以很好地处理小图像,但对大尺寸图像会造成严重破坏。 Application crashes with
OutOfMemoryError
. 应用程序与
OutOfMemoryError
崩溃。 If I try to increase inSampleSize
to 8 or 12, it works but image quality drastically comes down and image doesn't look original image at all. 如果我尝试将
inSampleSize
增加到8或12,它会起作用,但图像质量会大幅降低,图像看起来根本不会显示原始图像。 I tried with imageView.setImageURI(imageUri)
also but documentation suggests to use setImageBitmap
only. 我也尝试使用
imageView.setImageURI(imageUri)
但文档建议仅使用setImageBitmap
。
Now please someone help me to rectify this issue. 现在请有人帮我纠正这个问题。 How can I resolve this without compromising with image quality?
如何在不影响图像质量的情况下解决此问题?
A quick band-aid that might help would be to use: 一个快速的创可贴可能有助于使用:
opt.inPreferredConfig = Bitmap.Config.RGB_565;
That will load your images without an alpha channel, and only using 2 bytes per pixel (rather than 4 bytes with the default ARGB_8888). 这将加载没有alpha通道的图像,并且每个像素仅使用2个字节(而不是使用默认ARGB_8888的4个字节)。
Depending on the length of your list, you might have to load/unload your images as they become visible on screen/leave the screen. 根据列表的长度,您可能必须加载/卸载图像,因为它们在屏幕上可见/离开屏幕。
Try setting inSampleSize to 2 or 4, and scale width and height down using the Matrix
class. 尝试将inSampleSize设置为2或4,并使用
Matrix
类缩放宽度和高度。 But as you said in another answer, this may hit performance. 但正如你在另一个答案中所说,这可能会影响表现。
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
Second option. 第二种选择。 Before instantiating the Adapter class, get a Cursor object to thumbnail images and pass the cursor into the constructor of the adapter, making it a class varaible.
在实例化Adapter类之前,获取缩放图像的Cursor对象,并将光标传递给适配器的构造函数,使其成为可变类。 Use the same cursor on every view row in the ListView.
在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);
}
Something like that. 这样的事情。 I did it in a hurry.
我匆忙做了。 Good luck =)
祝你好运=)
尝试根据图像尺寸计算比例因子,并调用Bitmap.recycle()来释放分配的内存
First of all, as images are of 12mb(even if they are of only 1mb), you have to scale them and downsize them to the dimensions of your imageview
. 首先,因为图像是12mb(即使它们只有1mb),你必须缩放它们并将它们缩小到你的
imageview
的尺寸。
while you can also check for outofmemory exception
... 你还可以查看
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;
}
I also take assumption, you are doing all the decoding stuff in a background thread
to make your listview scroll
smooth... 我也假设,你在
background thread
中做所有解码的东西 ,使你的listview scroll
顺利...
While having many problems with Bitmaps
and ListView
, this was the best approach i can come with... still I am open for any changes or modifications or enhancments ... 虽然有很多问题
Bitmaps
和ListView
,这是最好的方法,我可以跟...还是我打开任何变更或修改,或enhancments ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.