Reputation: 1045
My thread is not stopped when onPause occurs, leading to a "thread already started" logcat error onResume as I can't have an two thread instances running. How do I terminate the thread at this point? I believe I need to do something like:
gameLoopThread.setRunning(false);
But I can't add that to my balloonBasic onPause, I think the context would be wrong. So help please, the code appears below. (code examples would be REALLY helpful, thanks)
My activity:
public class balloonBasic extends Activity {
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GameViewBasic(this));
}
public void onResume() {
super.onResume();
SoundManager.getInstance();
SoundManager.initSounds(this);
SoundManager.loadSounds();
}
public void onPause() {
super.onPause();
//what do I put here?
}
}
My surfaceview:
public class GameViewBasic extends SurfaceView {
...abbreviated declarations...
private static SurfaceHolder holder;
private static GameLoopThreadBasic gameLoopThread;
public GameViewBasic(Context context) {
super(context);
gameLoopThread = new GameLoopThreadBasic(this);
holder = getHolder();
holder.addCallback(new Callback() {
public void surfaceDestroyed(SurfaceHolder holder)
{
gameLoopThread.setRunning(false);
}
public void surfaceCreated(SurfaceHolder holder) {
createSprites();
mapspritegraphics();
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
}
});
}
...abbreviated for brevity....
My thread: public class GameLoopThreadBasic extends Thread { private GameViewBasic view; private volatile boolean running = false;
public GameLoopThreadBasic(GameViewBasic gameViewBasic) {
this.view = gameViewBasic;
}
public void setRunning(boolean run) {
running = run;
}
@Override
public void run() {
long ticksPS = 25; // =(1000/fps) ie 25ticksPS = 40fps
long startTime;
long sleepTime;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} catch (Exception f) {} //
finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = (ticksPS - (System.currentTimeMillis() - startTime));
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {}
}
}
}
Upvotes: 1
Views: 5232
Reputation: 294
I was working on a game a while ago, and I used LunarLander as inspiration in the early stages...but it turns out that the LunarLander sample code actually has that bug (trying to start a thread that is already running)! Below is a solution to the problem, in the class extending SurfaceView. I found the solution online somewhere, but I can't remember where because it was a long time ago.
public void surfaceCreated(SurfaceHolder holder)
{
if (mMyThreadName.getState() == Thread.State.TERMINATED)
{
mMyThreadName = new MyThreadName(xxx);
}
mSurfaceIsReady = true;
mMyThreadName.start();
}
Note that I also called mMyThreadName = new MyThreadName(xxx); in the constructor of the same class extending SurfaceView. I think my surfaceDestroyed callback worked the same as the LunarLander one, ie. mSurfaceIsReady was set to false in there, among other things.
EDIT
Android IllegalThreadStateException in LunarLander
It looks like there may be a better solution than the code I posted above. Instead, it may be possible to always just instantiate the thread in surfaceCreated, without checking if it was terminated, and don't instantiate it anywhere else. I haven't tried this second method though!
I may be misunderstanding your question, if I am I'm sorry.
Upvotes: 4