游戏线程执行在Android中无法正常恢复

时间:2015-04-11 20:56:49

标签: java android multithreading

我正在开发一个在自己的线程中运行的简单游戏。当我启动应用程序时,一切都很好。初始化线程,并从线程执行update()和render()函数,这很棒。

如果我退出应用程序,则会暂停该主题。当我再次启动应用程序时,该线程恢复正常。 (执行更新和渲染功能)。再次,这太棒了!

问题是,我按下电源按钮来睡觉设备。当我从这个状态恢复应用程序时,render()函数似乎工作正常;在我按下按钮之前,它正在绘制所有元素(背景,精灵等)。但是:精灵不再是动画!经过一些跟踪和故障排除后,我发现虽然"运行" flag设置为TRUE,好像是" RUN"功能不再运行! (另一方面,我很困惑为什么RENDER函数有效,但UPDATE函数没有,除非应用程序从其他方法渲染对象?无论如何......)

我从两个可能的角度来解决这个问题;我要么在Android操作我的线程的方式中遗漏了某些东西,要么这与对象中的成员变量已被重置的事实有关...

有人可以查看我在下面发布的基本代码,并就如何改进线程操作提出建议吗?我是一个聪明的人,我已经阅读了很多关于这个主题的不同来源的文章,现在比以往任何时候都更加困惑!我在这里走在正确的轨道上,还是有更聪明的方式做到这一点?我真的需要一个单独的游戏线程,还是可以使用设备的主线程来运行它?

感谢您的反馈!

public class GameThread extends Thread {
    private boolean running=false;
    private SurfaceHolder surfaceHolder;
    private GameView gameView;

    public GameThread(SurfaceHolder surfaceHolder, GameView gameView){
        super();
        this.surfaceHolder = surfaceHolder;
        this.gameView = gameView;
    }

    @Override
    public void run(){
        Canvas canvas;

        //  THIS ONLY RUNS ONCE!
        //  WHEN I TURN THE POWER OFF AND BACK ON, THE RUN() METHOD DOES NOT RUN!
        //  ODDLY ENOUGH, IF I WERE TO EXIT THE APP, AND GO BACK IN, IT WORKS FINE!
        //  THE running FLAG SEEMS TO CHANGE PROPERLY WHEN PAUSING OR RESUMING (SEE gameView, BELOW).
        while (running){
            canvas = null;
            try {
                canvas = this.surfaceHolder.lockCanvas();
                synchronized (surfaceHolder){
                    gameView.update();
                    gameView.render(canvas);
                }
            } finally {
                if (canvas!=null)
                    surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
    public void setRunning(boolean running){
        this.running = running;
    }
}

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

    public GameView(Context context) {
        super(context);
        gameScreen = new GameScreen(context);
        setFocusable(true);
        thread = new GameThread(getHolder(), this);
        getHolder().addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        thread = new GameThread(getHolder(), this);
        thread.setRunning(true);
        thread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        while (retry){
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e){
                // Do nothing; continue trying
            }
        }
    }

    public void render(Canvas canvas){
        gameScreen.draw(canvas);
    }   

    public void update(){   
        gameScreen.update();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        gameScreen.touch(event);
    }

    public void resume(){
        // TODO: Resume events go here
        thread.setRunning(true);
    }

    public void pause(){
        // TODO: Pause events go here
        thread.setRunning(false);
    }
}

public class GameScreen {
    public GameScreen(Context context){
        // Initialize private variables here
    }

    public void draw(Canvas canvas){
        // Draw events go here
    }

    public void update(){
        // Update events go here
    }

    public void touch(MotionEvent event){
        // Touch events go here
    }
}

1 个答案:

答案 0 :(得分:0)

在尝试发布画布之前,需要执行update()方法。仍然不确定为什么会这样,但它现在按预期工作。

    Canvas canvas = null;
    while (running){
        gameView.update();

        try {
            canvas = this.surfaceHolder.lockCanvas();
            synchronized (surfaceHolder){

                gameView.render(canvas);
            }
        } finally {
            if (canvas!=null)
                surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }
}