Android Custom Gallery Widget与java.lang.OutOfMemoryError崩溃:位图大小超过VM预算

时间:2011-10-01 16:58:01

标签: android android-widget

当在图片库上来回滚动很多次时,我的应用程序崩溃了:

java.lang.OutOfMemoryError:位图大小超过VM预算

我需要画廊垂直显示两张图片:

  • 最上面的一个将是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张图像一致地崩溃。

有更好的方法吗?

我做错了什么?

谢谢,

尼尔

2 个答案:

答案 0 :(得分:2)

在getView方法中,每次都创建一个ImageView。您可以像这样使用convertView:

        ImageView imageView;
        // if it's not recycled, initialize some attributes
        if (convertView == null) {
            imageView = new ImageView(mContext);
        } else {
            imageView = (ImageView) convertView;
        }

此外,您可以在位图上使用重新采样。

答案 1 :(得分:0)

这篇文章的评论19:code.google.com Issue 8488解决了这个问题。

我所要做的就是创建文件夹 res / drawable-nodpi 并将我正在呼叫的图像放在那里。

出于某种原因,如果您将图像存储在res / drawable中,则attr.recycle()无法正常工作。谁知道为什么?

我也实施了Tim的建议,似乎加快了在画廊中来回滚动。谢谢!

编辑:

上述答案适用于myTouch 4g,但程序仍然与G2崩溃。所以我接受了Tim的建议并开始考虑重新采样图像。我最后在这篇文章中使用了Fedor的答案: Strange out of memory issue while loading an image to a Bitmap object我从没见过G2上的内存不足问题。