Android:App在Back Pressed上崩溃 - SurfaceView

时间:2015-03-29 06:01:40

标签: java android android-activity android-canvas surfaceview

我正在开发一个Android应用程序,只是创建了背景画布。该应用程序加载正常,但当我按下后退按钮(即关闭应用程序) - 应用程序崩溃。看一下logcat(见下文),我得到一个NullPointerException。有人知道我可以解决这个问题吗?

以下是我的课程:

package pmm.antiaircraft1;

import android.app.Activity;
import android.view.Window;
import android.view.WindowManager;

public class GameActivity extends Activity {

  private GameThread mGameThread;

  public void onStart() {
    super.onStart();
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.main);
    mGameThread = ((GameView) findViewById(R.id.game)).getThread();
    mGameThread.createGraphics();
  }
}
package pmm.antiaircraft1;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;

public class GameThread extends Thread {
  private SurfaceHolder mSurfaceHolder;
  public DisplayMetrics metrics = new DisplayMetrics();
  private static Bitmap mBackgroundImage;
  public static Bitmap tankImg;
  public static Bitmap cannonImg;
  public static boolean mRun = false;
  private Tank tank;
  public static Resources res;

  public GameThread(SurfaceHolder surfaceHolder, Context context, Handler handler) {
    mSurfaceHolder = surfaceHolder;
    Resources res = context.getResources();
    mBackgroundImage = BitmapFactory.decodeResource(res, R.drawable.background);
    tankImg = BitmapFactory.decodeResource(res, R.drawable.tank);
    cannonImg = BitmapFactory.decodeResource(res, R.drawable.cannon);
  }

  @
  Override
  public void run() {
    while (mRun) {
      Canvas c = null;
      try {
        c = mSurfaceHolder.lockCanvas(null);
        synchronized(mSurfaceHolder) {
          draw(c);
        }
      } finally {
        if (c != null) {
          mSurfaceHolder.unlockCanvasAndPost(c);
        }
      }
    }
  }

  public void setRunning(boolean b) {
    mRun = b;
  }

  private void draw(Canvas canvas) {
    canvas.drawBitmap(mBackgroundImage, 0, 0, null);
    tank.draw(canvas);
  }

  public void createGraphics() {
    mBackgroundImage = Bitmap.createBitmap(mBackgroundImage);
    tank = new Tank();
  }
}
package pmm.antiaircraft5;

import android.content.Context;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameView extends SurfaceView implements SurfaceHolder.Callback {
  private GameThread thread;

  public GameView(Context context, AttributeSet attrs) {
    super(context, attrs);
    SurfaceHolder holder = getHolder();
    holder.addCallback(this);
    thread = new GameThread(holder, context, null);
  }

  public GameThread getThread() {
    return thread;
  }

  public void surfaceCreated(SurfaceHolder holder) {

    thread.setRunning(true);
    thread.start();

  }


  @
  Override
  public void surfaceChanged(SurfaceHolder holder, int format, int width,
    int height) {}

  @
  Override
  public void surfaceDestroyed(SurfaceHolder holder) {
    this.setWillNotDraw(false);

  }
}
package pmm.antiaircraft1;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;

public class Tank {
    private static final int TANK_HEIGHT = 50;
    private static final int TANK_WIDTH = 50;
    private static final int TANK_TOP = 480 - TANK_HEIGHT;
    private static final int CANNON_WIDTH = 10;

    public Tank(){
        GameThread.tankImg=Bitmap.createBitmap(GameThread.tankImg);
        GameThread.cannonImg=Bitmap.createBitmap(GameThread.cannonImg);
    }

    public void draw(Canvas c) {
        c.drawBitmap(GameThread.tankImg, (320-TANK_WIDTH)/2, TANK_TOP, null);   
        Matrix m = new Matrix();
        m.postTranslate((320-CANNON_WIDTH)/2, TANK_TOP - 30);
        c.drawBitmap(GameThread.cannonImg, m, null);    
    }
}

日志输出:

W/SurfaceView(400): CHECK surface infomation creating=false formatChanged=false sizeChanged=false visible=false visibleChanged=true surfaceChanged=true realSizeChanged=false redrawNeeded=false left=false top=false
**E/AndroidRuntime(400): FATAL EXCEPTION: Thread-88523
E/AndroidRuntime(400): java.lang.NullPointerException
E/AndroidRuntime(400): at pmm.antiaircraft1.GameThread.draw(GameThread.java:52)
E/AndroidRuntime(400): at pmm.antiaircraft1.GameThread.run(GameThread.java:37)**
W/SurfaceView(400): CHECK surface infomation creating=false formatChanged=false sizeChanged=false visible=false visibleChanged=false surfaceChanged=false realSizeChanged=false redrawNeeded=false left=false top=false
03-29 01:56:46.565: W/SurfaceView(400): CHECK surface infomation creating=false formatChanged=false sizeChanged=false visible=false visibleChanged=false surfaceChanged=false realSizeChanged=false redrawNeeded=false left=false top=false

1 个答案:

答案 0 :(得分:0)

SurfaceView生命周期与Activity生命周期不完全相同。如果您在lockCanvas()中检查run()的结果,并且在它为空时不尝试绘制,则应该能够避免崩溃而不会出现任何明显的故障。

为了更仔细地执行此操作并避免其他潜在问题,您需要使用Surface回调来跟踪当前状态。可以在图形架构文档中找到in an appendix的解释,并且可以在Grafika中找到示例(例如“multi-surface test”活动)。