2016-11-24 2 views
-1

Изначально моя игра потребляет безумный объем памяти около 500 МБ, а затем длится некоторое время примерно 5 раз, а затем падает.Android-игра потребляет безумный объем памяти при начальном запуске игры

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

Я не использовал никаких фреймворков и не узнал из этого tutorial, это мой проект в колледже. Однако я изменил большую часть кода в соответствии с игрой, которую я хотел сделать.

MyActivity.Java

public class MyActivity extends AppCompatActivity implements 
    View.OnClickListener { 
private AnimationDrawable animationDrawable; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_my); 

    //To portarit 
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
    RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.rlMy); 
    ImageButton buttonPlay = (ImageButton) findViewById(R.id.buttonPlay); 
    ImageButton buttonScore = (ImageButton) findViewById(R.id.buttonScore); 
    ImageButton buttonInstruction = (ImageButton) findViewById(R.id.buttonInstruction); 
    ImageButton buttonDeveloper = (ImageButton) findViewById(R.id.buttonDeveloper); 
    buttonPlay.setOnClickListener(this); 
    buttonScore.setOnClickListener(this); 
    buttonInstruction.setOnClickListener(this); 
    buttonDeveloper.setOnClickListener(this); 

    relativeLayout.setBackgroundResource(R.drawable.mainscreen); 

    animationDrawable = (AnimationDrawable) relativeLayout.getBackground(); 
    animationDrawable.start(); 
} 

private void clearData() { 
    try { 
     // clearing app data 
     Runtime runtime = Runtime.getRuntime(); 
     runtime.exec("pm clear com.lud.root.jetfighter;"); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

@Override 
public void onClick(View v) { 
    switch (v.getId()) 
    { 
     case R.id.buttonPlay: 
      startActivity(new Intent(this, GameActivity.class)); 
      finish(); 
      break; 
     case R.id.buttonScore: 
      startActivity(new Intent(this, HighScore.class)); 
      finish(); 
      break; 
     case R.id.buttonDeveloper: 
      startActivity(new Intent(this, WelcomeActivity.class)); 
      finish(); 
      break; 

     case R.id.buttonInstruction: 
      startActivity(new Intent(this, Instruction.class)); 
      finish(); 
      break; 

    } 
} 

@Override 
public void onBackPressed() { 
    AlertDialog.Builder builder = new AlertDialog.Builder(this); 
    builder.setMessage("Are You Sure you want to exit ?") 
      .setCancelable(false) 
      .setPositiveButton("Yes", new DialogInterface.OnClickListener() { 
       @Override 
       public void onClick(DialogInterface dialog, int which) { 
        GameView.stopMusic(); 
        Intent startMain = new Intent(Intent.ACTION_MAIN); 
        startMain.addCategory(Intent.CATEGORY_HOME); 
        startActivity(startMain); 
        finish(); 
       } 
      }) 
      .setNegativeButton("No", new DialogInterface.OnClickListener() { 
       @Override 
       public void onClick(DialogInterface dialog, int which) { 
        dialog.cancel(); 
       } 
      }); 
    AlertDialog alert = builder.create(); 
    alert.show(); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 
    System.gc(); 
    animationDrawable.start(); 
} 

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    this.releaseInstance(); 
    unbindDrawables(findViewById(R.id.rlMy)); 
} 

private void unbindDrawables(View view) { 
    if (view.getBackground() != null) { 
     view.getBackground().setCallback(null); 
    } 
    if (view instanceof ViewGroup) { 
     for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { 
      unbindDrawables(((ViewGroup) view).getChildAt(i)); 
     } 
     ((ViewGroup) view).removeAllViews(); 
    } 
} 
} 

GameView.JAVA

public class GameView extends SurfaceView implements Runnable{ 

volatile boolean playing; 
private Thread gameThread = null; 

//Adding the player to this class 
private Player player; 

//Objects used for drawing 
private Paint paint; 
private Canvas canvas; 
private SurfaceHolder surfaceHolder; 

//Add stars list 
private ArrayList<Star> stars = new ArrayList<Star>(); 

//Adding Enemies 
private Enemy[] enemies; // only one enemy to decrease the difficulty 
private int enemyCount = 3; // Number Of Enemies 

private Boom boom; 

int screenX; 
private boolean isGameOver; 

int score; 
int highScore[] = new int[6]; 
float distance[] = new float[enemyCount]; 

public SharedPreferences sharedPreferences; 
static MediaPlayer gameOnSound; 
final MediaPlayer gameOverSound; 

//Context to be used in onTouchEvent on GameOver Screen , for transition from 
//GameOver Screen to Main Activity 
Context context; 

public GameView(Context context, int screenX, int screenY) { 
    super(context); 
    player = new Player(context, screenX, screenY); 
    this.context = context; 

    //initialize drawing objects 
    surfaceHolder = getHolder(); 
    paint = new Paint(); 

    int starNums = 50; 
    for (int i = 0; i < starNums; i++){ 
     Star s = new Star(screenX,screenY); 
     stars.add(s); 
    } 

    enemies = new Enemy[enemyCount]; 
    enemies[0] = new Enemy(context, screenX, screenY); // This needs to be created so that the next enemies 
                 // created can be kept apart and not overlapping 
    for (int i=1; i<enemyCount; i++) 
     enemies[i] = new Enemy(context, screenX, screenY, enemies[i-1].getY(),enemies[i-1].getRadius()); 

    boom = new Boom(context); 

    boom.setX(-250); 
    boom.setY(-250); 

    this.screenX = screenX; 
    isGameOver = false; 

    score = 0; 
    sharedPreferences = context.getSharedPreferences("Scores", Context.MODE_PRIVATE); 

    //initialize the array of high scores 
    highScore[0] = sharedPreferences.getInt("score1",0); 
    highScore[1] = sharedPreferences.getInt("score2",0); 
    highScore[2] = sharedPreferences.getInt("score3",0); 
    highScore[3] = sharedPreferences.getInt("score4",0); 
    highScore[4] = sharedPreferences.getInt("score5",0); 

    gameOnSound = MediaPlayer.create(context,R.raw.gameon); 
    gameOverSound = MediaPlayer.create(context,R.raw.gameover); 

    gameOnSound.setLooping(true); 
    gameOnSound.start(); 

} 

@Override 
public void run() { 
    while (playing){ 
     update(); 
     draw(); 
     control(); 
    } 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    switch (event.getAction() & MotionEvent.ACTION_MASK){ 
     case MotionEvent.ACTION_UP: 
      //stopping the booster when the screen is released 
      player.stopSlowing(); 
      break; 
     case MotionEvent.ACTION_DOWN: 
      //starting the booster when the screen is released 
      player.startSlowing(); 
      break; 
    } 
    if(isGameOver){ 
     if(event.getAction() == MotionEvent.ACTION_DOWN) 
      context.startActivity(new Intent(context,MyActivity.class)); 
    } 
    return true; 
} 

private void update() { 
    //score based on the time passed 
    score++; 
    player.update(); 

    for(Star s : stars) 
     s.update(); 

    // Below Code is for multiple enemy 
    for(int i=0; i < enemyCount; i++){ 
     enemies[i].update((int) player.getSpeed() + 10); 
     distance[i] = (float) Math.sqrt((player.getX()-enemies[i].getX())*(player.getX()-enemies[i].getX()) + (player.getY()-enemies[i].getY())*(player.getY()-enemies[i].getY())); 
     if(distance[i] < (30 + enemies[i].getRadius())){ 
      boom.setX(player.getX()); 
      boom.setY(player.getY()); 
      player.setX(-200); 
      isGameOver = true; 
      playing = false; 
      gameOnSound.stop(); 
      gameOverSound.start(); 
      highScore[5] = score; 
      Arrays.sort(highScore); 
      Log.d("score","Score : "+score+"\nHighScores : "+highScore[0]+"\n"+highScore[1]+"\n"+highScore[2]+"\n"+highScore[3]+"\n"+highScore[4]+"\n"+highScore[5]); 

      SharedPreferences pref; 
      pref = context.getSharedPreferences("Scores", Context.MODE_PRIVATE); 
      SharedPreferences.Editor e = pref.edit(); 
      for(int j=0;j<5;j++){ 
       e.putInt("score"+(j+1),highScore[5-j]); 
       e.apply(); 
       Log.d("score","score"+(j+1)+"\nHighScores : "+highScore[5-j]); 
      } 
     } 
    } 

} 

private void draw() { 
    if(surfaceHolder.getSurface().isValid()){ 
     //lock the canvas 
     canvas = surfaceHolder.lockCanvas(); 
     canvas.drawColor(Color.BLACK); 

     //setting the paint color to white to draw the stars 
     paint.setColor(Color.WHITE); 

     //drawing all the stars 
     for (Star s : stars){ 
      paint.setStrokeWidth(s.getStarWidth()); 
      canvas.drawPoint(s.getX(), s.getY(), paint); 
     } 

     paint.setTextSize(30); 
     canvas.drawText("Score : "+score,100,50,paint); 

     //The following line is for single enemy 
     paint.setColor(Color.CYAN); 
     for(int i = 0; i< enemyCount; i++) 
      canvas.drawCircle(enemies[i].getX(), enemies[i].getY(), enemies[i].getRadius(), paint); 

     canvas.drawBitmap(boom.getBitmap(),boom.getX(),boom.getY(),paint); 
     paint.setColor(Color.RED); 
     canvas.drawCircle(player.getX(), player.getY(), player.getRadius(), paint); 
     if(isGameOver){ 
      paint.setTextSize(150); 
      paint.setTextAlign(Paint.Align.CENTER); 

      int yPos = (int)((canvas.getHeight()/2) - ((paint.descent() + paint.ascent()))/2); 
      canvas.drawText("GAME OVER",canvas.getWidth()/2, yPos,paint); 
     } 

     //Unlocking the canvas 
     surfaceHolder.unlockCanvasAndPost(canvas); 
    } 
} 

private void control() { 
    try { 
     gameThread.sleep(15); //creating the frame rate to around 33fps 
     canvas = null; 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

public void pause(){ 
    //pausing the game , set the variable to false 
    playing = false; 
    try { 
     gameThread.join(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

public void resume(){ 
    playing = true; 
    gameThread = new Thread(this); 
    gameThread.start(); 
} 

public static void stopMusic(){ 
    gameOnSound.stop(); 
    gameOnSound.release(); 
} 

public static void pauseMusic(){ 
    gameOnSound.pause(); 
} 

public static void resumeMusic(){ 
    gameOnSound.start(); 
} 
} 

Player.Java

public class Player { 
private Bitmap bitmap; 

//coordinates 
private int x; 
private int y; 

private float speed ; 
private boolean slowing, goingDown; 
private int GRAVITY = -10; // For the gravity effect on the ship 

//Boundaries 
private int maxY; 
private int minY; 
private int screenY; 
private float radius; 

private final float MINRADIUS = 30; 
private final float MAXRADIUS = 100; 

private final int POSGRAVITY = +10; 
private final int NEGGRAVITY = -10; 

private final int SLOWPOSGRAVITY = +4; 
private final int SLOWNEGGRAVITY = -4; 

public Player(Context context, int screenX, int screenY){ 
    x = 30; //initial x-position 
    y = 50; //initial y-position 
    speed = -4; 
    radius = MINRADIUS; 
    maxY = screenY - 30; 
    this.screenY = screenY; 
    minY = 30; //equal to initial radius 
    slowing = false; //initially slowing is false 
    goingDown = true; 
} 

public void startSlowing(){ 
    slowing = true; 
    if(radius > MAXRADIUS) 
     radius = MAXRADIUS; 
    else radius += 1.5f; 
    if(goingDown) 
    { 
     speed = -0.3f; 
     GRAVITY = SLOWNEGGRAVITY; 
    } 
    else{ 
     speed = 0.3f; 
     GRAVITY = SLOWPOSGRAVITY; 
    } 

} 

public void stopSlowing(){ 
    slowing = false; 
    if(goingDown) 
    { 
     speed = -4.0f; 
     GRAVITY = NEGGRAVITY; 
    } 
    else{ 
     speed = 4.0f; 
     GRAVITY = POSGRAVITY; 
    } 
} 

public void update(){ 
    minY = (int) getRadius(); 
    maxY = screenY - (int) getRadius(); 

    if(!slowing) 
     if(radius < MINRADIUS) 
      radius = MINRADIUS; 
     else radius -= 0.5f; 
    if(slowing) 
     if(radius > MAXRADIUS) 
      radius = MAXRADIUS; 
     else radius += 0.5f; 
    // Moving the ball down 
    y -= speed + GRAVITY; 
    if(y < minY) 
    { 
     y = minY; 
     if(slowing) 
     { 
      speed = -0.3f; 
      GRAVITY = SLOWNEGGRAVITY; 
     } 
     else 
     { 
      speed = -4; 
      GRAVITY = NEGGRAVITY; 
     } 
     goingDown = true; 
     Log.d("down","Gravity : "+ GRAVITY + " Speed : "+speed+" y : "+y+" goingDown : "+goingDown); 
    } 
    if(y > maxY) 
    { 
     y = maxY; 
     if(slowing) 
     { 
      speed = 0.3f; 
      GRAVITY = SLOWPOSGRAVITY; 
     } 
     else 
     { 
      speed = 4; 
      GRAVITY = POSGRAVITY; 
     } 
     goingDown = false; 
     Log.d("down","Gravity : "+ GRAVITY + " Speed : "+speed+" y : "+y+" goingDown : "+goingDown); 
    } 
} 

public float getSpeed() { 
    return speed; 
} 

public int getY() { 
    return y; 
} 

public int getX() { 
    return (int) (getRadius()); 
} 

public void setX(int x) { 
    this.x = x; 
} 

public float getRadius() { 
    return radius; 
} 
} 

Enemy.Java

public class Enemy { 

private int x; 
private int y; 
private int speed = -1; 
private int radius = 20; 

private int maxX, minX; 
private int maxY, minY; 

//Create a rect object to detect collision 
private Rect detectCollision; 

public Enemy(Context context, int screenX, int screenY){ 
    maxX = screenX; 
    maxY = screenY; 
    minX = 0; 
    minY = 0; 

    // Randomly generating enemy position 
    Random generator = new Random(); 
    speed = 25; 
    radius = 35; 
    x = screenX; 
    y = generator.nextInt(maxY) + 10 - radius; 
} 

public Enemy(Context context, int screenX, int screenY, int prevY, int prevRad){ 
    maxX = screenX; 
    maxY = screenY; 
    minX = 0; 
    minY = 0; 

    // Randomly generating enemy position 
    Random generator = new Random(); 
    speed = 25; 
    radius = 35; 
    x = screenX; 
    do{ 
     y = generator.nextInt(maxY) + 10 - radius; 
    }while ((y - prevY) < (prevRad + radius + 60)); 
} 

public void update(int playerSpeed){ 
    // As the enemy moves from right to left 
    x -= playerSpeed; 
    x -= speed; 
    Random generator = new Random(); 
    if(x < minX - this.getRadius()){ 
     speed = generator.nextInt(10) + 10; 
     radius = generator.nextInt(20) + 30; 
     x = maxX; 
     y = generator.nextInt(maxY) - radius; 
    } 
} 

//This setter is used for changing the x coordinate after collision 
public void setX(int x) { 
    this.x = x; 
} 

public Rect getDetectCollision() { 
    return detectCollision; 
} 

public int getSpeed() { 
    return speed; 
} 

public int getY() { 
    return y; 
} 

public int getX() { 
    return x; 
} 

public int getRadius() { 
    return radius; 
} 
} 

Star.Java

public class Star { 
private int x; 
private int y; 
private int speed; 

private int maxX; 
private int maxY; 
private int minX; 
private int minY; 

public Star(int screenX, int screenY){ 
    maxX = screenX; 
    maxY = screenY; 
    minX = 0; 
    minY = 0; 

    Random generator = new Random(); 
    speed = generator.nextInt(10); 

    //generate random coordinate but keeping them inside the screen 
    x = generator.nextInt(maxX); 
    y = generator.nextInt(maxY); 
} 

public void update(){ 
    //To animate the stars on the left side 
    //Used here is the player's speed 
    x -= 10; 
    x -=speed; 
    if(x < 0){ 
     //Again start the stars from the right edge 
     //Thus creating an infinite background effect 
     x = maxX; 
     Random generator = new Random(); 
     y = generator.nextInt(maxY); 
     speed = generator.nextInt(15); 
    } 
} 

public float getStarWidth(){ 
    //Randomising the star width , for aesthetics 
    float minX = 1.0f; 
    float maxX = 4.0f; 
    Random rand = new Random(); 
    return rand.nextFloat() * (maxX - minX) + minX; 
} 

public int getY() { 
    return y; 
} 

public int getX() { 
    return x; 
} 
} 

Все эти классы используют только метод холст рисовать, так что я предполагаю, что не должно быть никакой утечки памяти здесь, однако следующий класс Boom, который создает boom.png, когда вы теряете игру, использует растровое изображение, которое не кэшируется, это может быть проблемой, но только небольшая растровая карта не должна потреблять такой безумный объем памяти, я изменил рамку скорость с помощью элемента управления() в классе GameView, но все же ничего хорошего не выходит.

Boom.Java

public class Boom { 

private Bitmap bitmap; 
private int x,y; 

public Boom(Context context){ 
    //get the image from drawable 
    bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.boom); 

    //set the coordinate outside the screen so that it won't be 
    //shown on the screen 
    //it will be visible for only a fraction of a second 
    x = -250; 
    y = -250; 
} 

public int getY() { 
    return y; 
} 

public int getX() { 
    return x; 
} 

public Bitmap getBitmap() { 
    return bitmap; 
} 

public void setBitmap(Bitmap bitmap){ 
    this.bitmap = bitmap; 
} 

public void setY(int y) { 
    this.y = y; 
} 

public void setX(int x) { 
    this.x = x; 
} 
} 

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

Все эти (DDMS, Android Monitor, Tracing, Profiling), однако я сделал это и обнаружил, что (на основе данных в профилировании приложений в Android Monitor), это то, что я считаю прав, потому что раньше игра была работает только 3 - 4 раза, инструмент показал слишком много, взятые случайной функцией.

Ранее было 3 обращения к случайным в Enemy.java и 1 в Star.java

Я хочу знать причину и устранить то, что мешает моей игре.

Это из моего LogCat: (Я не вижу никаких сообщений dalvikvm, связанные с очисткой)

11-24 16:17:00.844 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:00.844 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:00.864 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:00.864 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:00.883 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:00.884 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:00.903 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:00.903 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:00.925 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:00.925 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:00.946 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:00.947 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:00.968 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:00.969 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:00.990 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:00.991 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.025 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.027 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.047 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.048 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.052 309 451 I BufferQueueProducer: [SurfaceView](this:0x7f8936e000,id:7877,api:2,p:2347,c:309) queueBuffer: fps=46.72 dur=1005.97 max=36.57 min=19.09 
11-24 16:17:01.067 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.067 2347 2466 I SurfaceView: Returned canvas: android.view.Surface$[email protected] 
11-24 16:17:01.087 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.088 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.107 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.107 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.126 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.127 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.147 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.147 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.170 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.171 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.192 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.193 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.215 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.215 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.249 2347 2466 I SurfaceView: Locking canvas... stopped=false, [email protected] 
11-24 16:17:01.250 2347 2466 I SurfaceView: Returned canvas: [email protected] 
11-24 16:17:01.273 2347 2347 D MediaPlayer: handleMessage msg:(8, 0, 0) 
11-24 16:17:01.276 2347 2466 D score : Score : 329 
11-24 16:17:01.276 2347 2466 D score : HighScores : 248 
11-24 16:17:01.276 2347 2466 D score : 269 
11-24 16:17:01.276 2347 2466 D score : 317 
11-24 16:17:01.276 2347 2466 D score : 329 
11-24 16:17:01.276 2347 2466 D score : 460 
11-24 16:17:01.276 2347 2466 D score : 579 
11-24 16:17:01.282 2347 2466 D score : score1 

Этот класс хозяйничает класс Gameview. GameActivity.CLAS

public class GameActivity extends AppCompatActivity{ 
    private GameView gameView; 

@Override 
protected void onCreate(@Nullable Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    //Get the display object 
    Display display = getWindowManager().getDefaultDisplay(); 
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

    //Get the screen Resolution 
    Point size = new Point(); 
    display.getSize(size); 
    //initialize the gameview object 
    gameView = new GameView(this, size.x,size.y); 
    setContentView(gameView); 

} 

@Override 
protected void onPause() { 
    super.onPause(); 
    gameView.pause(); 
    gameView.pauseMusic(); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 
    System.gc(); 
    gameView.resume(); 
    gameView.resumeMusic(); 
} 

@Override 
public void onBackPressed() { 
    startActivity(new Intent(this, MyActivity.class)); 
    finish(); 
} 

Это выход adb -d shell dumpsys meminfo com.lud.root.jetfighter команды

Выход памяти во время зависания игры

App Summary 
         Pss(KB) 
         ------ 
      Java Heap:  3348 
     Native Heap:  0 
       Code 

: 3320 Stack: 332 Графика: 25175 Частное другое: 11696 Система: 4691

   TOTAL: 48562  TOTAL SWAP (KB): 30220 

Objects 
       Views:  35   ViewRootImpl:  3 
     AppContexts:  5   Activities:  4 
       Assets:  4  AssetManagers:  2 
     Local Binders:  11  Proxy Binders:  18 
     Parcel memory:  3   Parcel count:  14 
    Death Recipients:  0  OpenSSL Sockets:  0 

HPROC Анализ моего изображения. Я не знаю, что сделать вывод, но я полагаю, что это ImageButton вызывает проблему:

enter image description here

+0

Вы должны использовать 'private final Random generator = new Random();' вместо того, чтобы создавать его все время. Это не должно быть так плохо, но когда инструмент жалуется, и средство является тривиальным, то обязательно решите пойти на это. – maaartinus

+0

Я пробовал этот @maaartinus, но все же игра вылетает, однако она не сработала при первом запуске. Спасибо – JDFuzyll

+0

в GameView.java onDraw метод, запишите, сколько из каждого элемента создано, я думаю, что вы делая много растрового изображения, и он будет потреблять много памяти. –

ответ

0

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

Одна вещь, которую я заметил, - это ваш метод рисования всегда рисует boom.png без регистрации, если игрок попал. Вместо того чтобы устанавливать значения x & y на отрицательные, то делая их положительными после удара, просто отслеживайте, если игрок попал. Вы уже делаете это с isGameOver. Просто передвиньте стрелу там, если нет другого примера, в котором вы его нарисовали (из того, что я могу сказать, нет).

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

+0

Я не вижу потоков мусора в сообщениях моего журнала .... Это может быть причина? Я видел logcat messsages от студии android, а также от терминала – JDFuzyll

+0

Я думаю, что я делаю новый экземпляр .... Я имею в виду да и как избежать этого, я опубликовал файл MyActivity.class и внесли изменения of Boom.png как предложено – JDFuzyll

+0

Похоже, вы достигли определенного прогресса. Вы можете попробовать установить «android: noHistory» в true в вашей GameActivity. Тогда вам не обязательно нужны все эти финишные звонки. Я продолжаю задаваться вопросом, сохраняете ли вы журнал журнала MainActivity. Вы никогда не заканчиваете его, что прекрасно, но каждый раз, когда вы заканчиваете игру, вы делаете новый экземпляр MainActivity. Каждая MainActivity имеет свою собственную копию ресурсов, которая включает в себя фоновый доступный. Я не уверен в этом, так как я не играл с этой ситуацией достаточно, но поскольку GameActivity довольно установлен, утечка может быть еще где-то. – WDude