最も有名なものに似た単語ゲームを開発しています。ボードには 15 x 15 のタイルがあります。タイルの色は 5 種類あります。
ボードは拡大できます。つまり、ボード全体を表示することも、2 倍に拡大することもできます。
アクティビティでボードを描画する 2 つの方法を実装しました。どちらも、私の Galaxy S とさまざまなエミュレーターで問題なくテストされています。どちらも大多数のデバイスで問題なく動作するようです。しかし、どちらも少数のユーザーに問題を引き起こします (これは私がここで解決しようとしていることです)。
2つのデザインの説明は次のとおりです。
オプション 1: 「大きな画像」
説明:
これは最も単純なものです。ボードはユニークですImageView
(ダブルタップのズームとドラッグを処理するためにサブクラス化されています)。画像 PNG リソースは高解像度です。ズームインしたときのアップスケーリングを避けるために、最大の画面サイズの 2 倍のサイズ。
問題: 大画面、特に 10 インチの Asus TF101 タブレットで時折発生することがある OutOfMemory の問題。
コメント: TF101 でのテストでは、RAM の使用量が Galaxy S の 3 倍であることを示しています。描画する必要がある巨大なスケーリングされたビットマップを考えると、これは論理的に思えます。
オプション 2: 5 つの小さな画像を繰り返す
説明: ビットマップが使用する RAM を削減し、ボードが 5 種類の小さな正方形の繰り返しであるという事実を利用しようとしました。ボード ビューのサイズ変更を簡単にするために、15 個のネストされた LinearLayout を含むカスタム LinearLayout にすることにしました。
4 x 4 ボードの XML レイアウトは次のようになります。
<MyCustomLinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" >
<ImageView
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1" >
</ImageView>
<ImageView
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1" >
</ImageView>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" >
<ImageView
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1" >
</ImageView>
<ImageView
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1" >
</ImageView>
</LinearLayout>
</MyCustomLinearLayout>
問題: 一部のユーザーの一部のクラッシュまたは視覚的な不具合。(この件に関してはまだ情報がありません)
コメント: 長所:このオプションの利点は、メモリ フットプリントが最適化されることです。5 つの小さなビットマップのそれぞれの 1 つのインスタンスのみがメモリに保持されます。ボードのサイズ変更は簡単です。Android は、MyCustomLinearLayout のサイズを変更すると、ビットマップとネストされた LinearLayout のすべてのサイズ変更を行います。
短所:ビューが多すぎるため、ズームのたびにシステムによって寸法を再計算する必要があります。
オプション 2 を改善して、RAM フットプリントを低く保ちながら、他のパフォーマンスの優れたプラクティス (数百のビューを持たないなど) を尊重するにはどうすればよいですか?
編集: 最終 (?) 実装
の代わりにSurfaceView
、シンプルなカスタムを選びView
ました。
メソッドで多くのビットマップ描画を行うonDraw()
と、ボードのドラッグが遅くなることが懸念されていました (onDraw()
ボードが移動されると常に呼び出されるため)。
これは非常にスムーズであることがわかりました (オプション 2 よりも少しスムーズかもしれません)。RAM の使用量については、オプション 2 (Eclipse Memory Analyzer を使用して比較) よりも少し重いだけなので、満足です。OutOfMemory エラー (「ビットマップが最大 VM ヒープ サイズを超えました」) の報告がまだいくつかありますが、ビットマップを使用する場合は避けられないと思います。
これが最も重要なコードで、ゲーム ボードを構築するために 15x15 ビットマップ (ビューのコンストラクターでリソースから初期化) を描画します。
public void drawTileAtCoordsOnCanvas(Bitmap bm, Canvas canvas, int x, int y) {
_rect.set(x * _sizeOfTile, y * _sizeOfTile, (x + 1) * _sizeOfTile, (y + 1) * _sizeOfTile);
canvas.drawBitmap(bm, null, _rect, _paint);
}
public void onDraw(Canvas canvas) {
for (int i = 0; i < _rules.BOARD_SIZE; i++) {
for (int j = 0; j < _rules.BOARD_SIZE; j++) {
switch (_rules._boardOfMultiplicators.get(i).get(j)) {
case NL:
drawTileAtCoordsOnCanvas(_bitmapNormalTile, canvas, i, j);
break;
case DL:
drawTileAtCoordsOnCanvas(_bitmapDlTile, canvas, i, j);
break;
case TL:
drawTileAtCoordsOnCanvas(_bitmapTlTile, canvas, i, j);
break;
case DW:
drawTileAtCoordsOnCanvas(_bitmapDwTile, canvas, i, j);
break;
case TW:
drawTileAtCoordsOnCanvas(_bitmapTwTile, canvas, i, j);
break;
}
}
}
drawTileAtCoordsOnCanvas(_bitmapStarTile, canvas, 7, 7);
}