我正在制作棋盘游戏,而我正在使用10x10 GridView作为棋盘。我已经创建了一个扩展BaseAdapter的ImageAdapter类,它包含一个Integer数组图标(9个补丁文件),这些用于显示电路板方块的图像。图标存储在res / drawable文件夹中,为629X629,平均大小约为5 KB。
我的ImageAdapter类具有以下getView()方法,它基本上循环使用相同的视图来节省内存:
编辑 :(我已经包含了在游戏活动中调用的changeIcon方法)
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)。我可以整天搬东西,一切都很好。
然而,一旦我将一个移动到另一个应用程序崩溃。预期的行为是创建一个新的部分。发生这种情况的代码如下:
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()只是更改该类中的字段类型(该片段变成新的东西)然后调用该类的方法setIcon()。此方法根据类型的值设置类的图标字段。并且,如上所述,图标是整数,指的是res / drawable中的九个补丁文件。
最后,从Activity GameBoardActivity调用方法move(int xFrom,int yFrom,int xTo,int yTo),成功移动后,Activity要求ImageAdapter(称为 adapter )重新绘制板,如下:
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字节分配时内存不足”的行是ImageAdapter的getView方法中的行imageView.setImageResource(mThumbIds[position]);
。
所以,就像我说的,一切顺利,直到我需要合并两个部分,然后我得到内存不足错误。值得注意的是,这个合并行为在应用程序的早期迭代中运行得非常好。
我现在应该提一下标准免责声明,因为我是一个完整的初学者,当涉及到java / android编码时,我已经看过其他有关类似问题的问题,但似乎没有其他人在处理他们的位图。我一样。
非常感谢任何帮助。 非常感谢你。
更新
通过进一步的测试,我注意到另一个奇怪的问题,即有时问题会发生,有时候不会发生,我无法确定在某些情况下导致崩溃的原因,而不是其他情况。更确切地说,完成相同的移动顺序可能会也可能不会导致崩溃。这很神秘。
答案 0 :(得分:6)
在您的代码中 mThumbIds 是 ID 的drawable。你应该做的是你必须通过以下代码创建特定图像的 Thumb 。
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。因此将创建此类大小的缩略图。