Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/193.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android:SurfaceView在surfaceDestroyed()之后停止重新绘制_Java_Android_Multithreading - Fatal编程技术网

Java Android:SurfaceView在surfaceDestroyed()之后停止重新绘制

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

我知道以前也有人问过类似的问题,但这些解决方案都不适合我

我正在尝试为Android创建一个小型2D游戏,但在使用SurfaceView时遇到了一些问题

我目前的主要活动如下:

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(),但随后不会重新创建它(画布不会重新绘制)
  • 游戏渲染线程从不停止(如日志消息所示)

您可能应该创建surfaceview onResume,而不是onCreate。它会被调用,或者用于活动的新实例,或者在恢复时调用。暂停时保留所需数据,恢复时恢复,基本上重新加载。您可以检查surfaceview是否已销毁,以避免每次都浪费时间重建,但如果需要,基本上可以准备就绪to@MiltoxBeyond我刚试过,但也没用。。游戏渲染线程仍然不会停止,并且SurfaceView在被销毁后不会重新创建。在暂停时,您还应该手动告诉线程暂停。哦,Android不会立即调用暂停,这取决于可用的资源。还有一个答案应该可以帮助你: