2013-02-13 3 views
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 в массиве Bitmap с методом BitmapFactory.decodeResource() и проведением растровых изображений, пока приложение будет уничтожено. Это отлично работает. Когда им swiching в портретном режиме, я изменить расположение с setContentView() и удалить keyboardSurfaceView:

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

растров загружаются один раз. Первый раз при переключении в альбомном режиме. Я столкнулся с ошибкой из памяти, когда swichtin до 10-20 раз от protrait в ландшафте и так далее. Когда я обновляю кучу в представлении ddms, я вижу, что каждый раз, когда я переключаюсь с представления protrait в ландшафтном представлении, размер кучи растет до ок. 20 МБ, а затем приложение выйдет из строя. Я не знаю, почему это происходит все время. Растровые изображения загружаются только один раз, а не каждый раз. Я также пробовал 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 

ответ

1

Вот Android документ о том, как обрабатывать растровое эффективно

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

+0

Я уже прочитал это, но безуспешно. Проблема заключается в растущей куче, хотя растровые изображения уже находятся в памяти – sNore

+0

Если да, можете ли вы разместить больше кода, поскольку код может содержать ошибку где-то еще. – Pongpat

0

ОК первый раз, когда surfaceCreated называется в моем классе surfaceView я вызываю этот метод, и этот метод вызывается только один раз, а не каждый раз, когда я показываю 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 к моему родительскому представлению в своем ландшафтном макете, а в портрете я удаляю его снова и загружаю макет портрета. Я делаю это в , потому что я самостоятельно обрабатываю изменения ориентации, поэтому приложение не уничтожается и не создается каждый раз при изменении ориентации устройства.

+0

ОК, его возможно, что это не сбой приложения сейчас. Я повернул девитов примерно 20-30 раз. после 6-7 оборотов он все еще выделяет больше памяти на кучу (но теперь только 300-400 кб). Когда размер кучи был достигнут, он разбился раньше, и теперь он только увеличил размер кучи. Я скопировал свои png-файлы во все доступные папки (mdpi, ldpi, xhdpi, hdpi). Но проблема существует в любом случае ... Я думаю, что это связано с масштабированием изображения ldpi, hdpi и т. Д. – sNore

Смежные вопросы