Android 自定义图库小组件因 java.lang.OutOfMemoryError 崩溃:位图大小超出 VM 预算
当在图像库上来回滚动多次时,我的应用程序崩溃并显示:
java.lang.OutOfMemoryError:位图大小超出虚拟机预算
我需要图库垂直显示两个图像:
- 顶部的图像将是从预图像中选择的图像res/drawable 文件夹中定义的图像组。
- 如果他们正确回答了该特定图像(这是游戏的提交分数页面),则底部图像将是一个绿色复选标记;如果他们回答错误,则底部图像将是一个带有线的红色圆圈。
这是我扩展 BaseAdapter 的代码:
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
TypedArray attr = mContext.obtainStyledAttributes(R.styleable.SubmitScoreGallery);
mGalleryItemBackground = attr.getResourceId(
R.styleable.SubmitScoreGallery_android_galleryItemBackground, 0);
attr.recycle();
}
@Override
public int getCount() {
return numQuestions;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Setup a LinearLayout to display the second image
LinearLayout lLayout = new LinearLayout(this.mContext);
lLayout.setOrientation(LinearLayout.VERTICAL);
//Create the ImageView
ImageView imageView = new ImageView(this.mContext);
imageView.setImageResource(imageList.get(randOrder.get(position)));
imageView.setLayoutParams(new Gallery.LayoutParams(gDispW, gDispH));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setBackgroundResource(mGalleryItemBackground);
lLayout.addView(imageView);
//Create the right/wrong image
ImageView imageViewBottom = new ImageView(lLayout.getContext());
if (score.getScoreAtIndex(position)== 1){
imageViewBottom.setImageResource(R.drawable.green_checkmark);
}
else{
imageViewBottom.setImageResource(R.drawable.incorrect_circle);
}
imageViewBottom.setLayoutParams(new Gallery.LayoutParams(gDispW, gDispH));
imageViewBottom.setPadding(gDispW/3, 0, gDispW/3, gDispH/2);
imageViewBottom.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
//imageViewBottom.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
lLayout.addView(imageViewBottom);
return lLayout;
}
}
randOrder 是一个保存图像顺序的数组。
图库可保存 5、10 或 15 张图像,具体取决于用户选择的问题数量。
我可以让它与 15 张图像一致地崩溃。
有更好的方法吗?
我做错了什么?
谢谢你,
尼尔
When scrolling back and forth a bunch of times on the image gallery my app crashes with:
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
I need the gallery to show two images vertically:
- The top one will be a selection from a pre-defined group of images in the res/drawable folder.
- The bottom image will be a green check mark if they answered this particular image correct (this is the submit your score page of the game) or a red circle with a line through it if they get it wrong.
Here is my code that extends the BaseAdapter:
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
TypedArray attr = mContext.obtainStyledAttributes(R.styleable.SubmitScoreGallery);
mGalleryItemBackground = attr.getResourceId(
R.styleable.SubmitScoreGallery_android_galleryItemBackground, 0);
attr.recycle();
}
@Override
public int getCount() {
return numQuestions;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Setup a LinearLayout to display the second image
LinearLayout lLayout = new LinearLayout(this.mContext);
lLayout.setOrientation(LinearLayout.VERTICAL);
//Create the ImageView
ImageView imageView = new ImageView(this.mContext);
imageView.setImageResource(imageList.get(randOrder.get(position)));
imageView.setLayoutParams(new Gallery.LayoutParams(gDispW, gDispH));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setBackgroundResource(mGalleryItemBackground);
lLayout.addView(imageView);
//Create the right/wrong image
ImageView imageViewBottom = new ImageView(lLayout.getContext());
if (score.getScoreAtIndex(position)== 1){
imageViewBottom.setImageResource(R.drawable.green_checkmark);
}
else{
imageViewBottom.setImageResource(R.drawable.incorrect_circle);
}
imageViewBottom.setLayoutParams(new Gallery.LayoutParams(gDispW, gDispH));
imageViewBottom.setPadding(gDispW/3, 0, gDispW/3, gDispH/2);
imageViewBottom.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
//imageViewBottom.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
lLayout.addView(imageViewBottom);
return lLayout;
}
}
randOrder is an array that holds the order of the images
The gallery holds 5, 10 or 15 images depending on how many questions the user chooses.
I can get it to crash consistently with the 15 images.
Is there a better way to do this?
What am I doing wrong?
Thank you,
Neil
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 getView 方法中,您每次都会创建一个 ImageView。您可以像这样使用convertView:
此外,您可以在位图上使用重采样。
On getView method, you create an ImageView every time. You can use convertView like this:
Moreover, you can use resampling on your bitmaps.
此帖子的评论 19:code.google.com 问题 8488 修复了该问题。
我所要做的就是创建文件夹 res/drawable-nodpi 并将我调用的图像放入其中。
由于某种原因,如果您将图像存储在 res/drawable 中,则 attr.recycle() 无法正常工作。有人知道为什么吗?
我还实施了蒂姆的建议,它似乎加快了画廊中来回滚动的速度。谢谢你!
编辑:
上面的答案适用于 myTouch 4g,但程序在 G2 上仍然崩溃。所以我采纳了蒂姆的建议并开始考虑对图像进行重新采样。我最终使用了 Fedor 在这篇文章中的答案:
将图像加载到位图对象时出现奇怪的内存不足问题,我还没有从那以后,G2 上再也没有出现过内存不足的问题。
Comment 19 of this post: code.google.com Issue 8488 fixed the issue.
All I had to do was create the folder res/drawable-nodpi and put the images that I am calling in there.
For some reason if you store your images in res/drawable the attr.recycle() doesn't work right. Anyone know why?
I also implemented Tim's suggestion and it seems to have sped up the scrolling back and forth in the gallery. Thank you!
EDIT:
The above answer worked for a myTouch 4g but the program still crashed with a G2. So I took Tim's advice and started to look at re-sampling images. I ended up using Fedor's answer from this post:
Strange out of memory issue while loading an image to a Bitmap object and I haven't seen the out of memory issues on the G2 since.