5

私はボード ゲームを作成しており、ボードには 10x10 の GridView を使用しています。アイコンの整数配列 (9 つのパッチ ファイル) を保持する BaseAdapter を拡張するクラス ImageAdapter を作成しました。これらは、ボードの正方形の画像を表示するために使用されます。アイコンは 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() を呼び出します。このメソッドは、type の値に応じて、クラスのアイコンフィールドを設定します。そして、前述のように、アイコンは res/drawable 内の 9 つのパッチ ファイルを参照する整数です。

最後に、メソッド move(int xFrom, int yFrom, int xTo, int yTo) がアクティビティ GameBoardActivity から呼び出され、移動が成功した後、アクティビティは 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 によると、「Fatal Signal 11」および「6330272 バイトの割り当てでメモリ不足」につながる行は、imageView.setImageResource(mThumbIds[position]);ImageAdapter の getView メソッドの行です。

したがって、私が言ったように、2 つの部分をマージする必要があるまではすべてうまくいきますが、メモリ不足のエラーが発生します。このマージ動作は、アプリの以前の反復で完全に正常に機能していたことも注目に値します。

私はJava/Androidでのコーディングに関しては完全な初心者であり、同様の問題に関連する他の質問を見てきましたが、私と同じ方法でビットマップを処理している人は誰もいないようです。午前。

どんな助けでも大歓迎です。どうもありがとうございました。

アップデート

さらなるテストを通じて、問題が発生する場合と発生しない場合があるという別の奇妙なことに気付きました。より正確に言えば、まったく同じ一連の動きを実行しても、クラッシュにつながる場合とそうでない場合があります。これはかなり謎です。

4

1 に答える 1

7

あなたのコードでは、 mThumbIdsはドローアブルのIDです。あなたがすべきことは、次のコードで特定の画像の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 のサンプル サイズを提供しています。このようなサイズのサムネイルが作成されます。

于 2013-04-24T06:30:06.037 に答える