Android游戏在游戏初始阶段消耗了大量内存

时间:2016-11-24 08:47:16

标签: java android performance memory-leaks bitmap

最初我的游戏耗费大约500MB的疯狂内存,然后运行大约5倍的时间然后崩溃。

我知道这是内存泄漏但无法识别所以我决定在这里上传整个代码并寻求社区的帮助。

我没有使用任何框架,并从这个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;
}
}

所有这些类都使用 only canvas method 进行绘制,所以我想这里不应该有任何内存泄漏,但是当你输掉游戏时创建一个boom.png的以下Boom类确实使用了一个没有被缓存的位图,这可能是问题,但只有一个小位图不应该消耗这么疯狂的内存量,我确实通过GameView类中的control()函数改变帧速率但是仍然没有什么好处出来

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次,该工具显示随机功能过多。

之前在 Enemy.java 中有3次随机调用, Star.java中有1次调用

我想了解根本原因并删除阻碍我游戏的因素。

这是来自我的logcat :(我没有看到任何与清理有关的dalvikvm消息)

11-24 16:17:00.844  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:00.844  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:00.864  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:00.864  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:00.883  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:00.884  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:00.903  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:00.903  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:00.925  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:00.925  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:00.946  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:00.947  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:00.968  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:00.969  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:00.990  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:00.991  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:01.025  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.027  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:01.047  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.048  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
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, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.067  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:01.087  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.088  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:01.107  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.107  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:01.126  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.127  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:01.147  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.147  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:01.170  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.171  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:01.192  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.193  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:01.215  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.215  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
11-24 16:17:01.249  2347  2466 I SurfaceView: Locking canvas... stopped=false, win=android.view.SurfaceView$MyWindow@ab77912
11-24 16:17:01.250  2347  2466 I SurfaceView: Returned canvas: android.view.Surface$CompatibleCanvas@cee38e3
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                    筹码: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分析我的形象。我不知道该结论,但我想这是引起问题的图像按钮:

enter image description here

1 个答案:

答案 0 :(得分:0)

我认为您在加载位图时阅读this会受益匪浅。根据我的个人经验,我发现如果没有正确完成,加载即使很小的位图也会导致内存大量消耗。

我注意到的一件事是,如果玩家被击中,你的绘制方法总是会引发boom.png。而不是设置x&amp; y值为负值然后在击中后使其成为正值,只需跟踪玩家是否被击中。您已经使用isGameOver执行此操作。只需移动那里的吊杆,除非有另一个需要绘制的实例(从我所知道的那里没有)。

除此之外,因为你说它在x次播放时崩溃了,我想知道它是否与你如何切换活动有关。假设您可以多次玩游戏并返回主菜单,我想知道您是否保留旧游戏视图的记录。你每次点击播放时都在创建一个新的GameView实例吗? (随意发布您的活动)