Java Android:SurfaceView在surfaceDestroyed()之后停止重新绘制
我知道以前也有人问过类似的问题,但这些解决方案都不适合我 我正在尝试为Android创建一个小型2D游戏,但在使用SurfaceView时遇到了一些问题 我目前的主要活动如下:Java Android:SurfaceView在surfaceDestroyed()之后停止重新绘制,java,android,multithreading,Java,Android,Multithreading,我知道以前也有人问过类似的问题,但这些解决方案都不适合我 我正在尝试为Android创建一个小型2D游戏,但在使用SurfaceView时遇到了一些问题 我目前的主要活动如下: public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private DrawingSurface drawingsurface; private Game game; @Overr
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private DrawingSurface drawingsurface;
private Game game;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate()");
setFullscreen();
game = new Game();
drawingsurface = new DrawingSurface(this, game);
setContentView(drawingsurface);
}
private void setFullscreen() {
// ...
}
public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback {
private GameThread thread;
private static final String TAG = "DrawingSurface";
public DrawingSurface(Context context, Game game) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
// create a new game rendering thread and pass it game so it can call the update() and render() functions of game:
thread = new GameThread(getHolder(), this, game);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v(TAG, "surfaceCreated()");
// start the rendering thread:
thread.setRunning(true);
thread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.v(TAG, "surfaceChanged()");
// do I need to do anything in here?
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// stop the rendering thread:
Log.v(TAG, "surfaceDestroyed()");
thread.setRunning(false);
boolean retry = true;
while (retry) {
try {
thread.join();
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// pass the touch event to the Game instance (to keep everything in on place)
thread.game.onTouchEvent(event);
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
// I don't use onDraw(), instead I have my own update() and render() functions in my game thread
super.onDraw(canvas);
}
}
如您所见,我将活动设置为全屏,创建一个新的SurfaceView(称为drawingSurface)并创建一个新的游戏实例
我的SurfaceView(称为DrawingSurface)如下所示:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private DrawingSurface drawingsurface;
private Game game;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate()");
setFullscreen();
game = new Game();
drawingsurface = new DrawingSurface(this, game);
setContentView(drawingsurface);
}
private void setFullscreen() {
// ...
}
public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback {
private GameThread thread;
private static final String TAG = "DrawingSurface";
public DrawingSurface(Context context, Game game) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
// create a new game rendering thread and pass it game so it can call the update() and render() functions of game:
thread = new GameThread(getHolder(), this, game);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v(TAG, "surfaceCreated()");
// start the rendering thread:
thread.setRunning(true);
thread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.v(TAG, "surfaceChanged()");
// do I need to do anything in here?
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// stop the rendering thread:
Log.v(TAG, "surfaceDestroyed()");
thread.setRunning(false);
boolean retry = true;
while (retry) {
try {
thread.join();
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// pass the touch event to the Game instance (to keep everything in on place)
thread.game.onTouchEvent(event);
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
// I don't use onDraw(), instead I have my own update() and render() functions in my game thread
super.onDraw(canvas);
}
}
这是我的游戏线索:
public class GameThread extends Thread {
private boolean running;
private SurfaceHolder surfaceHolder;
private DrawingSurface drawingSurface;
private static final String TAG = GameThread.class.getSimpleName();
protected Game game;
public GameThread(SurfaceHolder surfaceHolder, DrawingSurface drawingSurface, Game game) {
super();
this.surfaceHolder = surfaceHolder;
this.drawingSurface = drawingSurface;
this.game = game;
}
public void setRunning(boolean running) {
this.running = running;
}
@SuppressLint("WrongCall")
@Override
public void run() {
Log.d(TAG, "Starting game loop");
long now;
long dt;
long last = System.currentTimeMillis();
Canvas canvas;
while (running) {
Log.v(TAG, "GameThread running");
canvas = null;
/* try locking the canvas for exclusive
pixel editing in the surface */
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (this.surfaceHolder) {
now = System.currentTimeMillis();
dt = (now - last);
this.game.update(dt);
if(canvas != null)
this.game.render(canvas, dt);
last = now;
}
} finally {
/*in case of an exception the surface
is not left in an inconsistent state */
if (canvas != null) {
this.surfaceHolder.unlockCanvasAndPost(canvas);
}
}
if (dt < 16) {
try {
Thread.sleep(16 - dt);
} catch (InterruptedException e) {
}
}
}
}
公共类GameThread扩展线程{
私有布尔运行;
私人地勤人员地勤人员;
私人图纸表面图纸表面;
私有静态最终字符串标记=GameThread.class.getSimpleName();
受保护的游戏;
公共游戏线程(SurfaceHolder SurfaceHolder,DrawingSurface DrawingSurface,游戏){
超级();
this.surfaceHolder=surfaceHolder;
this.drawingSurface=drawingSurface;
这个游戏=游戏;
}
公共void setRunning(布尔运行){
这就是跑步;
}
@SuppressLint(“错误呼叫”)
@凌驾
公开募捐{
Log.d(标签“开始游戏循环”);
很久以前;
长dt;
long last=System.currentTimeMillis();
帆布;
(跑步时){
Log.v(标记“GameThread running”);
canvas=null;
/*尝试锁定画布以进行独占
曲面中的像素编辑*/
试一试{
canvas=this.surfaceHolder.lockCanvas();
已同步(this.surfaceHolder){
现在=System.currentTimeMillis();
dt=(现在-最后一次);
this.game.update(dt);
if(canvas!=null)
this.game.render(canvas,dt);
最后=现在;
}
}最后{
/*在异常情况下,表面
不会处于不一致的状态*/
if(canvas!=null){
此.surfaceHolder.unlockCanvasAndPost(画布);
}
}
if(dt<16){
试一试{
睡眠(16-dt);
}捕捉(中断异常e){
}
}
}
}
}
这是游戏课:
公开课游戏{
private static final String TAG = "Game";
private static int playerRefPosX = 40;
private int playerY = 0;
private int playerVelY = 1;
public Game() {
Log.v(TAG, "Game instance created");
}
public void update(long dt) {
playerY += playerVelY * dt;
if (playerY > 1800) {
playerVelY = -playerVelY;
}
if (playerY < 0) {
playerVelY = -playerVelY;
}
}
public void render(Canvas canvas, long dt) {
canvas.drawColor(Color.BLACK);
// draw Player
Paint paint = new Paint();
paint.setTextSize(100);
paint.setColor(new Color().rgb(255, 0, 0));
canvas.drawRect(playerRefPosX, playerY + 100, playerRefPosX + 200, playerY - 100, paint);
canvas.drawText(String.valueOf(1000/dt), canvas.getWidth()/2, canvas.getWidth()/2, paint);
}
public void onTouchEvent(MotionEvent event) {
Log.v(TAG, "received touch event..");
}
private static final String TAG=“Game”;
私有静态int playerRefPosX=40;
私有int playerY=0;
私人int playerly=1;
公共游戏(){
Log.v(标记“创建的游戏实例”);
}
公共无效更新(长dt){
playerly+=playerly*dt;
如果(游戏规则>1800){
playerly=-playerly;
}
if(playerY<0){
playerly=-playerly;
}
}
公共void渲染(画布,长dt){
画布。drawColor(颜色。黑色);
//平局球员
油漆=新油漆();
油漆.尺寸(100);
setColor(新颜色().rgb(255,0,0));
canvas.drawRect(playerRefPosX,playerry+100,playerRefPosX+200,playerry-100,paint);
drawText(String.valueOf(1000/dt)、canvas.getWidth()/2、canvas.getWidth()/2、paint);
}
公共事件(MotionEvent){
Log.v(标签“接收到的触摸事件”);
}
}
我现在面临的问题是:
- 当我按下home(主页)按钮并重新输入应用程序或旋转设备时,它会调用SurfacedStroyed(),但随后不会重新创建它(画布不会重新绘制)
- 游戏渲染线程从不停止(如日志消息所示)