在Android中,什么时候在SurfaceView中创建的Thread被破坏?

时间:2015-06-03 18:34:39

标签: java android multithreading surfaceview

我正在分析与James Cho's, "The Beginner's Guide to Android Game Development"相关联的代码,并且我遇到了与线程相关的一些令人困惑的逻辑,我希望得到帮助。我需要分析can be downloaded的完整源代码。

我寻求帮助的具体代码如下所示。请注意,我省略了与问题无关的代码。

public class GameView extends SurfaceView implements Runnable {
  private Thread gameThread;
  public GameView(Context context, int gameWidth, int gameHeight) {
    SurfaceHolder holder = getHolder();
    holder.addCallback(new SurfaceHolder.Callback() {
      @Override
      public void surfaceCreated(SurfaceHolder holder) {
        initGame();
      }
      @Override
      public void surfaceChanged(omitted) {omitted}
      @Override
      public void surfaceDestroyed(SurfaceHolder holder) {
        pauseGame();
      }
    });
    private void initGame() {
      gameThread = new Thread(this, "Game Thread");
      gameThread.start();
    }
    private void pauseGame() {
      while (gameThread.isAlive()) {
        try {
          gameThread.join(); 
          break;
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
}

我阅读此代码的方式,发生以下相关逻辑:

  1. 首次启动应用程序并显示GameView时,会创建一个新的Thread对象并与我们的gameThread变量相关联。
  2. gameThread命名,然后start()编辑。
  3. 如果应用失去焦点/暂停,并且gameThread正在运行,gameThread将通过join()方法暂停。 *请注意,这个逻辑*
  4. 有点模糊
  5. 如果应用重新获得焦点/重新启动,则会创建一个新线程并将其分配给我们的gameThread变量。
  6. 我对阅读这个逻辑的初步反应是,"为什么我们要创建一个新线程并将其分配给gameThread?不应该先前创建的线程仍然存在吗?"我做了一些调试/日志记录,并在游戏暂停和重新启动之间的某个时刻发现,gameThread线程被“销毁”,因为如果我尝试.getName()gameThread进行调用1}}在创建和分配新线程之前的initGame()期间,我得到一个空指针异常。如果现有的gameThread在暂停和恢复之间被销毁,那么是否会消除与该线程相关的任何游戏状态?

    有人可以告诉我线程发生的事情,因为应用程序失去了重点,然后重新获得它(或者指向我的资源)?

1 个答案:

答案 0 :(得分:0)

暂停或停止onPause()中的线程通常是一个好主意,这样在应用程序停止或不同的Activity中它们不会继续运行。此示例依靠surfaceDestroyed()暂停游戏,这是不够的,因为如果用户点击电源按钮以使显示屏空白,则表面可能不会被破坏。 (注意我没有超越你发布的内容,因此我不知道原始代码是否在onPause()中执行其他操作 - 如果它暂停线程活动那么它就没问题了。)

this article中详细介绍了SurfaceView与Activity生命周期之间的交互。我们假设您对Activity lifecycle有一定的了解。

您包含的pauseGame()方法是调用Thread.join(),它等待目标线程退出。 (它可以提前保释一个异常,这可能是为什么它包含在“while”循环中。)因此,当pauseGame()返回时,它保证了另一个线程不再运行。你没有包含的其他一些代码必须要求线程停止。