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)
来源:https://stackoverflow.com/questions/14013468/pausing-threads-properly-onpause-and-onresume-with-a-surfaceview-and-thread