Почему в моем приложении так много барана?

Поэтому я сделал игровое приложение, используя растровые изображения и обзор поверхности для школьного проекта. Но само приложение принимает так много бара! Только когда вы его начинаете, он может получить до 60 мб барана, и чем больше вы играете, тем выше он получает (в какой-то момент он добрался до 90 мб баранов, и игра была ужасно отстающей).

После просмотра Google I / O 2011 ( https://www.youtube.com/watch?v=_CruQY55HOk ) я рассмотрел, что это может быть утечка памяти, потому что приложение запускается следующим образом: Введите описание изображения здесь
И после игры 2 минуты это заканчивается так:
Введите описание изображения здесь

Само приложение было сделано максимально простым, с 8-битной графикой и несколькими цветами: Введите описание изображения здесь

Все изображения, которые я использовал весом ТОЛЬКО 400 КБ. Так почему, черт возьми, так много барана ?! Я думал, что это могут быть звуки, но все звуки объединяют вес всего лишь 4,45 бара, что соответствует 1/10 суммы, которую занимает приложение. Я понимаю, что растровые изображения занимают много барана, но это смешно!

Это мой onLoad:

public GameView(Context c) { // TODO Auto-generated constructor stub super(c); this.c = c; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; ScoreParticleP = new PointF(); NewScoreParticleP = new PointF(); int srcWidth = options.outWidth; int srcHeight = options.outHeight; // it=blocks.iterator(); // Decode with inSampleSize options.inJustDecodeBounds = false; options.inDither = false; options.inScaled = false; options.inPreferredConfig = Bitmap.Config.ARGB_8888; this.setKeepScreenOn(true); WindowManager wm = (WindowManager) c .getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); this.screenw = display.getWidth(); this.screenh = display.getHeight(); this.differencew = (double) screenw / normalw; this.differenceh = (double) screenh / normalh; try{ mediaPlayer = MediaPlayer.create(c, R.raw.nyan); while(mediaPlayer == null) { mediaPlayer = MediaPlayer.create(c, R.raw.nyan); } mediaPlayer.setLooping(true); if(mediaPlayer!=null) mediaPlayer.start(); } catch(Exception e){ } try{ mediaPlayer2 = MediaPlayer.create(c, R.raw.remix); while(mediaPlayer2==null){ mediaPlayer2 = MediaPlayer.create(c, R.raw.remix); } mediaPlayer2.setLooping(true); } catch(Exception e){ } try{ mediaPlayer3 = MediaPlayer.create(c, R.raw.weed); while(mediaPlayer3==null){ mediaPlayer3 = MediaPlayer.create(c, R.raw.weed); } mediaPlayer3.setLooping(true); } catch(Exception e){ } SharedPreferences prefs2 = c.getSharedPreferences( "Sp.game.spiceinspace", Context.MODE_PRIVATE); counter2 = prefs2.getInt("score", 0); this.sprite = BitmapFactory.decodeResource(getResources(), R.drawable.sprite, options); this.sprite = Bitmap.createScaledBitmap(sprite, sprite.getWidth() * 3, sprite.getHeight() * 3, false); this.heart = BitmapFactory.decodeResource(getResources(), R.drawable.heart); this.explosionheart=BitmapFactory.decodeResource(getResources(), R.drawable.explosionheart); this.heart = Bitmap.createScaledBitmap(heart, heart.getWidth() * 3, heart.getHeight() * 3, false); currentSpeed = new PointF(0, 0); currentDirection = new Point(0, 0); currentPosition = new Point(350, 350); this.background = BitmapFactory.decodeResource(getResources(), R.drawable.space); this.background2=BitmapFactory.decodeResource(getResources(), R.drawable.space2); this.electricExplosion = BitmapFactory.decodeResource(getResources(), R.drawable.effect_explosion); this.normalexplison = BitmapFactory.decodeResource(getResources(), R.drawable.effect_explosion2); this.background = Bitmap.createScaledBitmap(background, background.getWidth() * 5, background.getHeight() * 5, false); this.background2 = Bitmap.createScaledBitmap(background2, background2.getWidth() * 5, background2.getHeight() * 5, false); this.lost = BitmapFactory.decodeResource(getResources(), R.drawable.gameover); this.lostNew = BitmapFactory.decodeResource(getResources(), R.drawable.gameovernew); lostNew = FitAllDevices(lostNew); lost = FitAllDevices(lost); this.alien = BitmapFactory.decodeResource(getResources(), R.drawable.mob_alien); this.coin = BitmapFactory.decodeResource(getResources(), R.drawable.item_coin); partic = BitmapFactory.decodeResource(getResources(), R.drawable.particle_star); fire = BitmapFactory.decodeResource(getResources(), R.drawable.particle_fire); smoke = BitmapFactory.decodeResource(getResources(), R.drawable.particle_smoke); partic = Bitmap.createScaledBitmap(partic, partic.getWidth() * 2, partic.getHeight() * 2, false); fire = Bitmap.createScaledBitmap(fire, fire.getWidth() * 2, fire.getHeight() * 2, false); smoke = Bitmap.createScaledBitmap(smoke, smoke.getWidth() * 2, smoke.getHeight() * 2, false); electricExplosion = Bitmap.createScaledBitmap(electricExplosion, electricExplosion.getWidth() * 2, electricExplosion.getHeight() * 2, false); normalexplison = Bitmap.createScaledBitmap(normalexplison, normalexplison.getWidth() * 3, normalexplison.getHeight() * 3, false); this.alien = Bitmap.createScaledBitmap(alien, alien.getWidth() * 3, alien.getHeight() * 3, false); asteroid = BitmapFactory.decodeResource(getResources(), R.drawable.mob_astroid); bomb = BitmapFactory.decodeResource(getResources(), R.drawable.mob_spacebomb); asteroid = Bitmap.createScaledBitmap(asteroid, asteroid.getWidth() * 3, asteroid.getHeight() * 3, false); bomb = Bitmap.createScaledBitmap(bomb, bomb.getWidth() * 3, bomb.getHeight() * 3, false); goldasteroid = BitmapFactory.decodeResource(getResources(), R.drawable.mob_goldastroid); goldasteroid = Bitmap.createScaledBitmap(goldasteroid, goldasteroid.getWidth() * 3, goldasteroid.getHeight() * 3, false); mushroom = BitmapFactory.decodeResource(getResources(), R.drawable.item_mushroom); mushroom = Bitmap.createScaledBitmap(mushroom, mushroom.getWidth() * 4, mushroom.getHeight() * 4, false); coin = Bitmap.createScaledBitmap(coin, coin.getWidth() * 2, coin.getHeight() * 2, false); drug = BitmapFactory .decodeResource(getResources(), R.drawable.item_not); drug = Bitmap.createScaledBitmap(drug, drug.getWidth() * 4, drug.getHeight() * 4, false); rocket = BitmapFactory.decodeResource(getResources(), R.drawable.item_rocket); rocket = Bitmap.createScaledBitmap(rocket, rocket.getWidth() * 4, rocket.getHeight() * 4, false); electricExplosion = FitAllDevices(electricExplosion); alien = FitAllDevices(alien); normalexplison = FitAllDevices(normalexplison); explosionheart = FitAllDevices(explosionheart); mushroom = FitAllDevices(mushroom); drug = FitAllDevices(drug); rocket = FitAllDevices(rocket); bomb = FitAllDevices(bomb); asteroid = FitAllDevices(asteroid); goldasteroid = FitAllDevices(goldasteroid); sprite = FitAllDevices(sprite); heart = FitAllDevices(heart); player = new Spicy(sprite, heart); hit = soundPool.load(c, R.raw.hit, 1); pass = soundPool.load(c, R.raw.win, 1); //remix = soundPool.load(c, R.raw.remix, 1); destroy = soundPool.load(c, R.raw.destroy, 1); aliensound = soundPool.load(c, R.raw.alien, 1); alienexpload = soundPool.load(c, R.raw.explosion2, 1); //particlesound = soundPool.load(c, R.raw.particle, 1); bigexplosion=soundPool.load(c, R.raw.explosion, 1); gameLoopThread = new GameLoopThread(this); this.requestFocus(); this.setFocusableInTouchMode(true); holder = getHolder(); holder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceDestroyed(SurfaceHolder holder) { boolean retry = true; gameLoopThread.setRunning(false); while (retry) { try { gameLoopThread.join(); retry = false; } catch (InterruptedException e) { } } } public void surfaceCreated(SurfaceHolder holder) { if (gameLoopThread.getState()==Thread.State.TERMINATED) { gameLoopThread = new GameLoopThread(g); } gameLoopThread.setRunning(true); gameLoopThread.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } }); } 

Я делаю что-то неправильно? Мое приложение – это всего лишь небольшая игра с растровыми изображениями, выходящими с одной стороны и идущими на другую сторону, сначала она начинает медленно, но чем больше вы играете, тем больше битмапов идет, я бы понял это количество бара, если было много растровых изображений на Экран, но он занимает 60 Мб, когда на экране нет ничего, кроме плеера и фона!

Я буду рад написать всем пользователям приложение, чтобы попытаться понять, насколько просто это, но сколько раз он берет без причины ..


Редактировать:

Я упомянул, что приложение со временем занимает больше времени, я понимаю, что это связано с тем, что я создаю новые растровые изображения и перемещаю их, а затем удаляю их, и чем больше вы играете, тем больше растровых изображений создаются, но я стараюсь Лучше удалить их сразу после и переработать их, чтобы убедиться, что они собраны сборщиком мусора. Интересно, как я могу свести к минимуму количество использования и все-таки сделать игру более доступной:

Это то, как я «создаю» мобы (моб получает растровое изображение, которое я загрузил onLoad):

 private void spawnMob() { if (timer2 == 0) { int mobtype = randInt(1, 40); switch (mobtype) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: Mob m = new Mob(alien, MobEffect.comeback, 1); Point p = new Point(0, 0); py = randInt(0, screenh - alien.getHeight()); px = screenw + alien.getWidth(); spawned.put(p, m); break; case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: case 32: Mob m2 = new Mob(asteroid, MobEffect.dissapire, 0); Point p2 = new Point(0, 0); p2.y = randInt(0, screenh - asteroid.getHeight()); p2.x = screenw + asteroid.getWidth(); spawned.put(p2, m2); break; case 33: case 34: case 35: case 36: case 37: case 38: case 39: Mob m3 = new Mob(goldasteroid, MobEffect.dissapire, 1); Point p3 = new Point(0, 0); p3.y = randInt(0, screenh - goldasteroid.getHeight()); p3.x = screenw + goldasteroid.getWidth(); spawned.put(p3, m3); case 40: if (counter > 3) { Mob m4 = new Mob(bomb, MobEffect.expload, 1, 5, false, false); Point p4 = new Point(0, 0); p4.y = randInt(0, screenh - bomb.getHeight()); p4.x = screenw + bomb.getWidth(); spawned.put(p4, m4); } else { Mob m5 = new Mob(asteroid, MobEffect.dissapire, 0); Point p5 = new Point(0, 0); p5.y = randInt(0, screenh - asteroid.getHeight()); p5.x = screenw + asteroid.getWidth(); spawned.put(p5, m5); } break; } if (rocketspeed >= 10) { timer2 = randInt(1, 8); } else { if (bleedoff != 35) { if (bleedoff > 1) timer2 = randInt(35 / (int) bleedoff, 150 / (int) bleedoff); else timer2 = randInt(35, 150); } else timer2 = randInt(1, 10); } } else { timer2--; } } 

И на onDraw я убеждаюсь удалить мобов, чтобы они не занимали дополнительную память, когда их нет на экране:

  Iterator<Map.Entry<Point, Mob>> spawnedEntry = spawned .entrySet().iterator(); while (spawnedEntry.hasNext()) { Map.Entry<Point, Mob> entry = spawnedEntry.next(); if(entry.getValue().destroycomplete||entry.getValue().dissapired){ spawnedEntry.remove(); } else entry.getValue().draw(canvas, entry.getKey()); 

Также по классу Mob:

 if(!MobEffectstarted) if(!destroycomplete) c.drawBitmap(mob,px,py, null); else mob.recycle(); 

Изменить 2:

Это то, что говорит мне инструмент памяти затмения: Введите описание изображения здесь
Это определенно растровые изображения.


Введите описание изображения здесьВведите описание изображения здесь

Почему мое приложение использует столько оперативной памяти при запуске?

Ваши исходные файлы изображений сжимаются. Вы распаковываете их и сохраняете полную растровую карту в памяти. (О rowBytes * height в байтах, узнать размер растрового изображения ). Вы также многократно изменяете их размер ; Например, фоны масштабируются до пятикратного первоначального размера. Поскольку изображения имеют два измерения, объем памяти масштабируется квадратично.

Пример: изображение размером 500×500; Он выделяет 4 байта между строками (32-битный режим). Это приводит к растровому размеру 500×4 x 500 = 1 МБ.

Если вы масштабируете это изображение в 2 раза, вы выделяете не в два раза больше памяти, а: 1000×4 x 1000 = 4 МБ

Что я могу сделать?

  • Если вам не нужен альфа-канал, вам может понадобиться уменьшить глубину бит ваших растровых изображений. Например, Bitmap.Config.RGB_565 используя Bitmap.Config.RGB_565 .
  • Не загружайте большие растровые изображения, чем необходимо, указав размер выборки. (Подробнее об этом здесь: Загрузка больших растровых изображений )
  • Убедитесь, что вы повторно используете как можно больше растровых изображений.
  • Загружать растровые изображения только в случае необходимости. Вам нужны оба фона одновременно?
  • Ваш фон, кажется, только градиент; Вы можете использовать класс LinearGradient для рисования, избавляя вас от огромного фонового изображения. (То же самое относится к вашим квадратам, если они не просто заполнители).

Что касается утечек памяти в вашем коде:

  • Убедитесь, что вы постоянно не создаете новых мобов. Сохраните «мертвых» мобов в отдельном списке и поместите их обратно в список участников, когда это необходимо. Создавайте только новые, когда у вас на самом деле заканчиваются «ожидающие» мобы.
  • Не создавайте объекты в методах, которые вызываются много. (Например, любой метод draw (), если на то пошло.)

Если вы тестируете на pre-Honeycomb, вам нужно переработать любые выделенные растровые изображения, поскольку в противном случае они могут не освободиться из исходной памяти.

Intereting Posts
Службы Google Play: как проверить, есть ли в настоящий момент «активный» ожидающий обратный вызов намерения, зарегистрированный для обновления местоположения или распознавания активности? Остановка приложения Android с консоли AnimationDrawable не играет Откат Android sqlite Android findViewWithTag для просмотров с несколькими тегами Android Studio 4.0 застрял в обновлении, не может запускать проект Как автоматически импортировать необходимые классы в Android Studio с помощью ярлыка? Java Android AsyncTask – Когда AsyncTask перестает работать? API11 (и теперь12) и Spannable, приводящий к запуску NPE Как предоставить посетителям автономный доступ к данным CouchDB на мобильном сайте? Использование подчеркивания в именах хостов Разница между предпочтением и общим предпочтением в Android Ручки выбора не отображаются в WebView (Android 4.0-4.3) Поддерживает ли Android Webview поддержку CSS3 WebKit Animations? AutoCompleteTextView – запрет выпадающего списка при закрытии при вызове notifyDataSetChanged