setImageResource 内存不足错误 [英] Out of memory Error on setImageResource

查看:71
本文介绍了setImageResource 内存不足错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个棋盘游戏,我正在为棋盘使用 10x10 GridView.我制作了一个类 ImageAdapter 扩展 BaseAdapter ,它包含一个整数数组图标(9 个补丁文件),这些用于显示棋盘方块的图像.图标存储在 res/drawable 文件夹中,大小为 629X629,平均大小约为 5 KB.

I'm making a board game, and I'm using a 10x10 GridView for the board. I've made a class ImageAdapter extending BaseAdapter which holds an Integer array of icons (9 patch files), and these are used to display the images for the squares of the board. The icons are stored in the res/drawable folder, are 629X629 and average about 5 KB in size.

我的 ImageAdapter 类有如下 getView() 方法,它本质上是回收同一个视图以节省内存:

My ImageAdapter class has the following getView() method, which essentially recycles the same view to save memory:

编辑:(我已经包含了在游戏活动中调用的 changeIcon 方法)

EDIT: (I've included the changeIcon method which gets called in the Activity for the game)

public View getView(int position, View convertView, ViewGroup parent) {
    ImageView imageView;
    if (convertView == null) {  // if it's not recycled, initialize some attributes
        imageView = new ImageView(mContext);
        imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setPadding(8, 8, 8, 8);
    }
    else{
        imageView = (ImageView) convertView;
    }


    imageView.setImageResource(mThumbIds[position]);
    return imageView;
}

public void changeIcon(int x, int y, Integer icon){
    int position = (9-y)*10 + x;
    mThumbIds[position] = icon;
    getView(position, currentView, null);
}

我有一个名为 Game 的单独类,用于处理游戏的逻辑.我将这些棋子存储在 Piece[][] 数组中,其中 Piece 是我为保存游戏(你猜对了)棋子的数据而创建的另一个类.相关的是处理棋子移动的方法 move(int xFrom, int yFrom, int xTo, int yTo).我可以整天移动碎片,一切都很好.

I have a separate class called Game where the logic of the game is handled. I store the pieces in a Piece[][] array, where Piece is another class I've made to hold the data for (you guessed it) pieces of the game. Of relevance is the method move(int xFrom, int yFrom, int xTo, int yTo) which handles the movement of pieces. I can move pieces around all day and everything is fine.

但是,一旦我将一块移入另一块,应用程序就会崩溃.预期的行为是创建一个新作品.发生这种情况的代码如下:

However, once I move one piece into another the app crashes. The intended behaviour is that a new piece gets created. The code where this happens is below:

public boolean move(int xFrom, int yFrom, int xTo, int yTo){

    boolean success = false;
    Piece pieceToMove = getPiece(xFrom,yFrom);
    Piece pieceAtDest = getPiece(xTo,yTo);
    int moveTeam = pieceToMove.getTeam();

    if(isLegalMove(xFrom, yFrom, xTo, yTo, pieceToMove)&&(turn == moveTeam)){
        if( pieceAtDest == null)
        {
           /*I do something when the destination piece is null; 
                       this block causes no problems */   
        }
        else{
            success = true;
            pieceToMove.merge();
            position[xTo][yTo] = pieceToMove;
            position[xFrom][yFrom] = null;
        }
    }
    return success;
}

因此,违规调用是pieceToMove.merge().Piece 类中的方法 merge() 只是更改该类中的字段 type(该部分变成了新的东西),然后调用该类的方法 setIcon().此方法根据类型的值设置类的 icon 字段.而且,如上所述,图标是整数,指的是 res/drawable 中的九个补丁文件.

So, the offending call is pieceToMove.merge(). The method merge() in the class Piece simply changes the field type in that class (the piece becomes something new) then calls the method setIcon() of that class. This method sets the icon field of the class depending on the value of type. And, as mentioned above, icons are Integers referring to the nine patch files in res/drawable.

最后,Activity GameBoardActivity 调用了 move(int xFrom, int yFrom, int xTo, int yTo) 方法,在成功移动后,Activity 要求 ImageAdapter(称为 适配器)重绘板子,如下:

Finally, the method move(int xFrom, int yFrom, int xTo, int yTo) was called from the Activity GameBoardActivity, and after a successful move the Activity asks the ImageAdapter (called adapter) to redraw the board, as follows:

boolean success = game.move(xFrom,yFrom,xTo,yTo);

if(success){

Integer destIcon = game.getPiece(xTo, yTo).getIcon();
Piece pieceAtDep = game.getPiece(xFrom, yFrom);
Integer depIcon;
if(pieceAtDep == null)
    depIcon = R.drawable.square;
else
    depIcon = game.getPiece(xFrom, yFrom).getIcon();
adapter.changeIcon(xTo,yTo,destIcon);
adapter.changeIcon(xFrom,yFrom,depIcon);
gridView.setAdapter(adapter);
}

Logcat 表示导致致命信号 11"和内存不足 6330272 字节分配"的行是 imageView.setImageResource(mThumbIds[position]); 行ImageAdapter 的 getView 方法.

The Logcat says that the line leading to the "Fatal Signal 11" and "Out of memory on a 6330272-byte allocation" is the line imageView.setImageResource(mThumbIds[position]); in the getView method of ImageAdapter.

所以,就像我说的,一切都很好,直到我需要合并两个部分,然后出现内存不足错误.还值得注意的是,这种合并行为在应用程序的早期迭代中运行良好.

So, like I said, everything goes along fine until I need to merge two pieces, then I get the out of memory error. It is also worth noting that this merge behaviour was working perfectly fine in an earlier iteration of the app.

现在我应该提到标准免责声明,因为我在 java/android 中编码时是一个完整的初学者,并且我已经查看了与类似问题相关的其他问题,但似乎没有其他人在处理他们的位图和我一样.

I should mention the standard disclaimer now that I am a complete beginner when it comes to coding in java/android, and that I have looked at other questions relating similar issues, but no one else seems to be handling their bitmaps in the same way I am.

非常感谢任何帮助.非常感谢.

Any help is greatly appreciated. Thank you very much.

更新

通过进一步的测试,我注意到另一个奇怪的现象,即有时会出现问题,有时不会,而且我无法确定在某些情况下是什么导致崩溃,而在其他情况下我无法确定是什么原因导致崩溃.更准确地说,执行完全相同的动作序列可能会也可能不会导致崩溃.这很神秘.

Through further testing I've noticed another oddity which is that, sometimes the problem occurs, and sometimes not, and I cannot identify what causes crashes in some instances and not others. To be more precise, doing the exact same sequence of moves may or may not lead to a crash. This is quite mysterious.

推荐答案

在你的代码中 mThumbIds 是 drawable 的 Ids.您应该做的是您必须通过以下代码创建特定图像的拇指.

In your code mThumbIds are Ids of drawable. What you should do is you have to create a Thumb of particular image by following code.

public static 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;
}

public static Bitmap decodeSampledBitmapFromResource(Resources res,
        int resId, int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth,
            reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
} 

使用此代码,

decodeSampledBitmapFromResource(getResources(),R.drawable.xyz, 100, 100);

这里,您提供的样本大小为 100 * 100.因此将创建这样大小的缩略图.

Here, 100 * 100 sample size you are providing. So Thumbnail of such size will be created.

这篇关于setImageResource 内存不足错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆