title: Pausing threads properly onPause() and onResume() with a SurfaceView and Thread in Android
body: <p>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.</p>
  
  <p>My activity instantiates the GamePanel and my GamePanel instantiates the GameThread.</p>
  
  <p>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 (<em>see edit #1</em>) every time I tried to resume the app.</p>
  
  <p>So instead to fix the problem I just re-instantiated the thread,</p>
  
  <pre><code>thread = new GameThread(getHolder(), this);
  </code></pre>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>Here is the code (I left out a few lines that didn't seem relevant):</p>
  
  <p>GameActivity:</p>
  
  <pre><code>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();
  }
  </code></pre>
  
  <p>GamePanel</p>
  
  <pre><code>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);
  }
  </code></pre>
  
  <p>GameThread</p>
  
  <pre><code>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);
              }
          }
      }
  }
  </code></pre>
  
  <p>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?).</p>
  
  <p>A little help will go a long way. Thanks in advance if you can give any suggestions.</p>
  
  <p><strong>--EDIT #1--</strong></p>
  
  <p>This was my log cat error when I got a force close.</p>
  
  <pre><code>12-23 14:01:34.288: E/AndroidRuntime(9484): java.lang.IllegalThreadStateException: Thread already started.
  </code></pre>
  
  <p><strong>--EDIT #2--</strong></p>
  
  <p>I tried what you said and changed my run() method to:</p>
  
  <pre><code>@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) {
              }
          }
      }
  }
  </code></pre>
  
  <p>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)</p>