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() 方法将位图加载到位图数组中,并保存位图直到应用程序被销毁。这很好用。当我在纵向模式下切换时,我使用 setContentView() 更改布局并删除 keyboardSurfaceView :

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

位图加载一次。第一次切换横向模式。我遇到了内存不足的错误,当从横向的 protrait 等进行 10-20 次切换时,等等。当我在 ddms 视图中更新堆时,我可以看到,每次当我从横向视图中的 protrait 视图切换时,堆大小都会增长到 ca。20mb 然后应用程序崩溃。我不知道为什么这一直在发生。位图只加载一次,而不是每次。我也试过bitmap.recycle(); bitmap = null没有成功。还尝试使用 LRUCache 类缓存位图,如 Google 最佳实践中所述。我还搜索了 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

好的第一次在我的surfaceView类中调用surfaceCreated时,我调用了这个方法,并且这个方法只调用一次,而不是每次我在屏幕上显示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();
        }
}

而已。每次在横向时,我都会在横向布局中将我的 SurfaceView 添加到我的父视图中,在纵向中我再次将其删除,然后加载我的纵向布局。我这样做是onConfigurationChanged()因为我自己处理方向更改,因此每次更改设备方向时都不会破坏和创建应用程序。

于 2013-02-14T11:30:48.730 回答