8

私はアンドロイドゲームに取り組んでいます。背景に 3 つの画像を使用しようとすると、問題が発生します。画像は 1280x720px で 100kb です。画像は実際にはそれほど大きくないので、なぜメモリの問題が発生するのか少し混乱しています。

注: 画面の解像度は 800x400 であるため、Android 開発者で推奨されているように、画像を 2 倍にサイズ変更することはできません 注: 私は HTC 欲望の電話を使用しています (ここでクラッシュが発生します)。それは正常に動作します。

DDMS でメモリを分析したところ、ヒープのサイズが 3.5 MB しかないことがわかりました。rt.MaxMemory() をチェックすると、アプリごとに約 25 MB のスペースがあると表示されます。

私の頭に浮かぶのは、ヒープがより大きな写真/アプリに対応するのに十分な速さで「更新」されていないため、非常に小さいにもかかわらず、画像をロードする前にクラッシュすることです. ヒープサイズを手動で設定する方法はありますか、または少なくとも拡大するように指示する方法はありますか?

画像をロードするコードは次のとおりです。

        Bitmap floorFront = BitmapFactory.decodeResource(host.getResources(), R.drawable.floor1);
        floorFront = Bitmap.createScaledBitmap(floorFront,host.realWidth,host.realHeight, true);
        floorFront = Bitmap.createBitmap(floorFront, 0, host.realHeight/2, host.realWidth, host.realHeight/2);
        host.addInstance(new Background(0,host.realHeight/2,host,floorFront,1));

        Bitmap floorBack = BitmapFactory.decodeResource(host.getResources(), R.drawable.sand);
        floorBack = Bitmap.createScaledBitmap(floorBack,host.realWidth,host.realHeight, true);
        floorBack = Bitmap.createBitmap(floorBack, 0, host.realHeight/2, host.realWidth, host.realHeight/2);
        host.addInstance(new Background(0,host.realHeight/2,host,floorBack,4));

        Bitmap floorRock = BitmapFactory.decodeResource(host.getResources(), R.drawable.foreground);
        floorRock = Bitmap.createScaledBitmap(floorRock,host.realWidth,host.realHeight, true);
        floorRock = Bitmap.createBitmap(floorRock, 0, host.realHeight/2, host.realWidth, host.realHeight/2);
        host.addInstance(new Background(0,host.realHeight/2,host,floorRock,0));

LogCat からの正確なエラーは次のとおりです。

 maxMemory:25165824
 memoryClass:24
 6144000-byte external allocation too large for tgis process.
 Out of memory: Heap Size=4739KB, Allocated=2399KB, Bitmap Size=18668KB
 VM won't let use allocate 6144000bytes

編集:ビットマップが「生の」サイズの画像を使用し、圧縮されていないことは理にかなっていると言いました。そして、いくつかの調査の後、Android 2.2および2.3ではビットマップがヒープに保存されていないため、画像がロードされた後にヒープが増加しないようです。

もう 1 つ質問があります。この 3 枚の画像を背景に使用します。垂直方向に少しサイズを変更しますが、水平方向にはまだ必要です。したがって、画像はまだ約 100x720px です。3 つの画像が必要な理由は、それらを別々に描画してレイヤー効果を得ることができるためです (2 つの画像の間に何かを描画できます)。使用するメモリをできるだけ少なくして望ましい効果を得るためにこれを実装する最良の方法は何でしょうか?

背景: バックグラウンド 中: 真ん中 前景 前景

注: これは静的な背景にすぎません。アニメーションは背景と背景の間で発生します。

4

1 に答える 1

4

1280 x 720 ピクセルのビットマップが 100KB であることがどこで得られるかわかりません。本当に数メガバイトです。バイト単位では 1280 * 720 * ですが、1 ピクセルあたりのバイト数は通常、透明度のある画像の場合は 4 バイト、透明度のない画像の場合は 2 バイトです。携帯電話が読み込むには膨大な量のデータです。PNG などの圧縮された画像形式のバージョンのサイズを引用している可能性があります。

メモリ使用量の問題に対処するためのヒント:

透過性がない場合は、ファクトリで Bitmap.Config.RGB_565 入力形式を使用します。これにより、ARGB_8888 よりもスペースが節約されます。

AndroidManifest.xml の application 要素で largeHeap を true に設定します。

デバイス密度クラスに基づいてビットマップが自動的にスケーリングされていないことを確認してください。たとえば、それらを drawable-nodpi に配置するか、自動スケーリングをプログラムで無効にするか、複数のドローアブル フォルダー内の密度クラスごとに異なるビットマップを提供します。ビットマップがドローアブル フォルダーにのみある場合、XHDPI デバイスでは 2 倍にスケーリングされます。

使用していないビットマップをリサイクルします。例:

Bitmap floorFront = BitmapFactory.decodeResource(host.getResources(), R.drawable.floor1);
Bitmap floorFrontScaled = Bitmap.createScaledBitmap(floorFront,host.realWidth,host.realHeight, true);
floorFront.recycle();
floorFront = null;

Bitmap floorFrontCropped = Bitmap.createBitmap(floorFrontScaled, 0, host.realHeight/2, host.realWidth, host.realHeight/2);
host.addInstance(new Background(0,host.realHeight/2,host,floorFrontCropped,1));

System.gc() を手動で実行することもできます。システムは OutOfMemoryError を返す前にそれを行うことになっていますが、Android のビットマップには Java の外部にメモリが割り当てられているため、それは行われません。

ビットマップを読み込むときは、実際に必要なサイズがそのサイズよりも小さい整数除数であるかどうかを確認し、ロード時にファクトリがピクセルをスキップするように指定できることに注意してください。これは、対応するメモリ制限が小さい解像度の小さいデバイスで役立ちます。

これらの背景画像を個別に移動しない場合は、一度に 3 つではなく、すべてを 1 つのビットマップに描画し、それを使用します。

于 2012-10-27T23:35:46.327 に答える