Pausing threads properly onPause() and onResume()

2020-06-28 01:34发布

问题:

To run the games that I've created on Android, I've been using a GamePanel contains the methods onDraw() and onTouch(). I also have been using a GameThread class that calls onDraw() and update() repeatedly.

My activity instantiates the GamePanel and my GamePanel instantiates the GameThread.

My onPause() just sets the condition in the while-loop inside the thread, run, to false. My onResume() used to just set that equal to true, however that would give me a force close error (see edit #1) every time I tried to resume the app.

So instead to fix the problem I just re-instantiated the thread,

thread = new GameThread(getHolder(), this);

This solved part of the problem, allowing me to minimize the app and then re-open it without a problem. However, when I was in the app and I locked my phone and then unlocked it (turning the screen on and off) the thread would never start. It would just be my game in a frozen state.

I know that my solution to the problem is extremely funky, and I would love to learn a more accepted and clean way to do this whole thing.

Here is the code (I left out a few lines that didn't seem relevant):

GameActivity:

void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    gamePanel = new MainGamePanel(this);
    setContentView(gamePanel);

}
protected void onPause() {
    super.onPause();
    gamePanel.shutDown();

}
protected void onResume() {
    super.onResume();
    gamePanel.startUp();
}

GamePanel

public MainGamePanel(Context context) {
    super(context);
    getHolder().addCallback(this);                  //adding the callback (this) to the surface  holder to intercept events
    thread = new GameThread(getHolder(), this);     // create the game loop thread
    setFocusable(true);                             // make the GamePanel focusable so it can handle events
}
public void startUp() {
    thread = new GameThread(getHolder(), this);
}

public void shutDown() {
    thread.setRunning(false);
}

GameThread

public GameThread(SurfaceHolder surfaceHolder, MainGamePanel gameView) {
    this.surfaceHolder = surfaceHolder;
    this.gameView = gameView;
    this.run = true;
}
public void setRunning(boolean run) {
    this.run = run;
}
public void run() {
    Canvas c;//
    while (run) {
        c = null;
        try {
            c = surfaceHolder.lockCanvas(null);
            synchronized (surfaceHolder) {                  
                gameView.update();
                gameView.onDraw(c);
            }
        } finally {
            if (c != null) {
                surfaceHolder.unlockCanvasAndPost(c);
            }
        }
    }
}

Let me know if you need more information or how I can make my question more clear (also, did I present my code in an understandable manor?).

A little help will go a long way. Thanks in advance if you can give any suggestions.

--EDIT #1--

This was my log cat error when I got a force close.

12-23 14:01:34.288: E/AndroidRuntime(9484): java.lang.IllegalThreadStateException: Thread already started.

--EDIT #2--

I tried what you said and changed my run() method to:

@Override
public void run() {
    Canvas c;
    while (true) {
        if (run) {/* run game thread */
            c = null;
            try {
                c = surfaceHolder.lockCanvas(null);
                synchronized (surfaceHolder) {
                    gameView.update();
                    gameView.onDraw(c);
                }
            } finally {
                if (c != null) {
                    surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        } else {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
            }
        }
    }
}

It worked when I locked my phone, but when I minimized the app and reopened it I was presented with a black screen and after a few seconds a popup that said "MyApp isn't responding. Do you want to close it?". I checked where it got up to and it seemed to get to the onPause() and the shutDown() but it never got to onResume();. Also, sometimes it even calls update() after it calls onPause() or shutDown(), which is weird. (Got the info from LogCat)