Addev
Addev

Reputation: 32243

SurfaceView and thread already started exception

Checking the LunarLander example it uses that code for resume the drawer thread:

public void surfaceCreated(SurfaceHolder holder) {
    // start the thread here so that we don't busy-wait in run()
    // waiting for the surface to be created
    thread.setRunning(true);
    thread.start();
}

and this for end:

public void surfaceDestroyed(SurfaceHolder holder) {
    // we have to tell thread to shut down & wait for it to finish, or else
    // it might touch the Surface after we return and explode
    boolean retry = true;
    thread.setRunning(false);
    while (retry) {
        try {
            thread.join();
            retry = false;
        } catch (InterruptedException e) {
        }
    }
}

But when I execute the project, press the home button and resume the application it crashes with

 java.lang.IllegalThreadStateException: Thread already started.
    at java.lang.Thread.start(Thread.java:1045)
    at com.example.android.lunarlander.LunarView.surfaceCreated(LunarView.java:862)
    at android.view.SurfaceView.updateWindow(SurfaceView.java:533)
    at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:226)
    at android.view.View.dispatchWindowVisibilityChanged(View.java:5839)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:945)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:945)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:945)
    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:945)

I've seen this method for handling the background thread in other examples but it crashes. What is the problem with it?

Upvotes: 0

Views: 5021

Answers (3)

Elawry kip
Elawry kip

Reputation: 11

This is how I solved this issue. In the surfaceCreated method, the state of the thread may have changed to TERMINATED. You need to create the thread a new.

@Override
 public void surfaceCreated(SurfaceHolder holder) {
     bgSurfaceThread = bgSurfaceThread.getState().equals(Thread.State.TERMINATED) ? bgSurfaceThread : new BackgroundSurfaceThread(BackgroundSurfaceView.this);
    bgSurfaceThread.setRunning(true);
   bgSurfaceThread.start();
}

Upvotes: 0

gaomode
gaomode

Reputation: 176

You can do it like this:

@Override
public void surfaceCreated(SurfaceHolder holder) {
    if (!thread.isAlive()) {
        thread.start();
    }
}

Upvotes: 0

fonZ
fonZ

Reputation: 2479

Your thread is still running, you dont stop it correctly i guess. You have to interrupt your thread or thats how i solved it. So instead of using setRunning and a boolean to make your thread run you use something like this:

to start it:

public void surfaceCreated(SurfaceHolder holder) {
    thread.start();
}

In the thread:

public void run() {

    try {
        while (true) {
            // code here
        }
    }
    catch (InterruptedException e) {
         //disable stuff here
    }
}

And to stop it:

public void surfaceDestroyed(SurfaceHolder holder) {
    thread.interrupt();
}

I just typed this quickly but it should give you an idea.

Upvotes: 5

Related Questions