0

アプリに問題があります。ランドスペース モードに切り替えると、 setContentView() メソッドが呼び出されてピアノ キーボードが表示されます。ピアノ キーボード クラスは、Surfaceview を拡張して、押されたキーを表示するパフォーマンスを向上させます。この SurfaceView クラスは、ランドスケープ レイアウトの子として追加されます。

RelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.rootLayout);
RelativeLayout.LayoutParams relativeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
relativeLayoutParams.addRule(RelativeLayout.BELOW, R.id.relativeLayoutLowerBar);
rootLayout.addView(keyboardSurfaceView, relativeLayoutParams); 

私のkeyboardSurfaceViewクラスでは、BitmapFactory.decodeResource()メソッドを使用してBitmap配列にビットマップをロードし、アプリが破棄されるまでビットマップを保持しています。これはうまくいきます。ポートレートモードで切り替えると、setContentView() でレイアウトを変更し、keyboardSurfaceView を削除します。

if(keyboardSurfaceView != null && keyboardSurfaceView.getParent() != null)
        ((ViewGroup) keyboardSurfaceView.getParent()).removeView(keyboardSurfaceView);

ビットマップは一度ロードされます。ランドスケープモードで切り替えたのは初めて。ランドスケープなどで protrait から最大 10 ~ 20 回切り替えたときに、メモリ不足のエラーが発生しました。ddms ビューでヒープを更新すると、プロトレイト ビューからランドスケープ ビューに切り替えるたびに、ヒープ サイズが約 1.5 倍に大きくなっていることがわかります。20MB で、アプリがクラッシュします。なぜこれがいつも起こっているのかわかりません。ビットマップは毎回ではなく一度だけロードされます。私も試しましたbitmap.recycle(); bitmap = null成功せずに。また、Google のベスト プラクティスで説明されているように、LRUCache クラスを使用してビットマップをキャッシュしようとしました。また、問題の適切な解決策についてstackoverflowを検索しました。これはまだ修正できません。縦横の変更を自分で処理します (onConfigurationChanged() メソッドをオーバーライドします)。すべての画像を drawable-xhdpi に入れると少し効果がありました。方向を変更すると、ヒープ サイズは以前と同じように大きくなりますが、まだ大きくなっています。どんな助けでも大歓迎です...

例外:

 02-13 22:44:09.419: E/dalvikvm-heap(935): 11448-byte external allocation too large for this process.
02-13 22:44:09.419: E/dalvikvm(935): Out of memory: Heap Size=16391KB, Allocated=13895KB, Bitmap Size=16394KB, Limit=32768KB
02-13 22:44:09.419: E/dalvikvm(935): Trim info: Footprint=16391KB, Allowed Footprint=16391KB, Trimmed=432KB
02-13 22:44:09.419: E/GraphicsJNI(935): VM won't let us allocate 11448 bytes
4

2 に答える 2

1

ビットマップを効率的に処理する方法のAndroidドキュメントは次のとおりです

http://developer.android.com/training/displaying-bitmaps/index.html

于 2013-02-13T22:09:10.170 に答える
0

初めてsurfaceCreatedがsurfaceViewクラスで呼び出されたときに、このメソッドを呼び出します。このメソッドは1回だけ呼び出され、画面にsurfaceViewを表示するたびに呼び出されるわけではありません。

bitmapKeyboard = BitmapFactory.decodeResource(context.getResources(), R.drawable.keyboard); 

bitmapGlowImages[0] = BitmapFactory.decodeResource(context.getResources(), R.drawable.keycdown); 
bitmapGlowImages[1] = BitmapFactory.decodeResource(context.getResources(), R.drawable.blackkeydown);
bitmapGlowImages[2] = BitmapFactory.decodeResource(context.getResources(), R.drawable.keyddown);
bitmapGlowImages[3] = BitmapFactory.decodeResource(context.getResources(), R.drawable.blackkeydown);
bitmapGlowImages[4] = BitmapFactory.decodeResource(context.getResources(), R.drawable.keyedown);
bitmapGlowImages[5] = BitmapFactory.decodeResource(context.getResources(), R.drawable.keycdown); 
bitmapGlowImages[6] = BitmapFactory.decodeResource(context.getResources(), R.drawable.blackkeydown);
bitmapGlowImages[7] = BitmapFactory.decodeResource(context.getResources(), R.drawable.keyddown);
bitmapGlowImages[8] = BitmapFactory.decodeResource(context.getResources(), R.drawable.blackkeydown);
bitmapGlowImages[9] = BitmapFactory.decodeResource(context.getResources(), R.drawable.keyddown);
bitmapGlowImages[10] = BitmapFactory.decodeResource(context.getResources(), R.drawable.blackkeydown);
bitmapGlowImages[11] = BitmapFactory.decodeResource(context.getResources(), R.drawable.keyedown);

このクラスでは、別のスレッドを実行して、押されたキーを描画しcanvas.drawBitmap(bitmap, null, destRect, null)ます。最後に、onDestroyが呼び出されると、メソッドrecycleBitmaps()が呼び出されます。

public void recycleBitmaps() {
        if(bitmapKeyboard != null) {
            bitmapKeyboard.recycle();
            bitmapKeyboard = null;
            for(int i = 0; i < bitmapGlowImages.length; i++) {
                bitmapGlowImages[i].recycle();
                bitmapGlowImages[i] = null;
            }
            System.gc();
        }
}

それでおしまい。そして、ランドスケープでは毎回、サーフェスビューをランドスケープレイアウトの親ビューに追加し、ポートレートでは再度削除して、ポートレートレイアウトをロードします。向きの変更は自分で処理するonConfigurationChanged()ので、デバイスの向きを変更するたびにアプリが破棄されたり作成されたりすることはありません。

于 2013-02-14T11:30:48.730 に答える