【问题标题】:How to best pause and resume a surfaceView thread如何最好地暂停和恢复 SurfaceView 线程
【发布时间】:2013-05-05 04:30:11
【问题描述】:

发生 onPause 时我的线程没有停止,导致 onResume 出现“线程已启动”logcat 错误,因为我无法运行两个线程实例。此时如何终止线程?我相信我需要做类似的事情:

gameLoopThread.setRunning(false);

但我不能将它添加到我的 balloonBasic onPause 中,我认为上下文是错误的。所以请帮忙,代码如下所示。 (代码示例真的很有帮助,谢谢)

我的活动:

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?
}
}

我的表面视图:

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....

我的话题: 公共类 GameLoopThreadBasic 扩展线程 { 私有 GameViewBasic 视图; 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) {}
         }
   }
}

【问题讨论】:

  • 调用gameLoopThread.setRunning(false)有什么问题;在你的暂停?您应该停止线程,即让它完成执行并保存您的状态。
  • 因为我的 onPause 在 balloonBasic 中,它会告诉我“gameLoopThread 无法解析”,因为它出现在我的surfaceview GameViewBasic 中。我认为这是一个我无法理解的上下文问题?

标签: android multithreading


【解决方案1】:

前段时间我正在开发一款游戏,我在早期阶段使用 LunarLander 作为灵感……但事实证明,LunarLander 示例代码实际上存在该错误(试图启动一个已经在运行的线程) ! 下面是该问题的解决方案,在扩展 SurfaceView 的类中。我在某处网上找到了解决方案,但我不记得在哪里,因为那是很久以前的事了。

public void surfaceCreated(SurfaceHolder holder)
{
    if (mMyThreadName.getState() == Thread.State.TERMINATED)
    {
        mMyThreadName = new MyThreadName(xxx);
    }

    mSurfaceIsReady = true;
    mMyThreadName.start();
}

请注意,我还调用了 mMyThreadName = new MyThreadName(xxx);在扩展 SurfaceView 的同一类的构造函数中。我认为我的 surfaceDestroyed 回调与 LunarLander 一样,即。 mSurfaceIsReady 在那里被设置为 false 等等。

编辑

Android IllegalThreadStateException in LunarLander

看起来可能有比我上面发布的代码更好的解决方案。相反,可以始终只在surfaceCreated 中实例化线程,而不检查它是否已终止,并且不要在其他任何地方实例化它。不过我还没有尝试过第二种方法!

我可能误解了你的问题,对不起。

【讨论】:

  • 但这会在第一次运行创建线程之前检查线程,因此会导致空指针异常。我正在尝试修改它以检查是否为 null 并采取相应措施,但还没有运气。如果您可以检查您的实际应用程序,它可能会澄清一些事情,否则您可能会记得如何修改上述内容。
  • 你可能错过了我说的这部分:“我在扩展 SurfaceView 的同一个类的构造函数中也调用了 mMyThreadName = new MyThreadName(xxx);”
  • 诚然,在两个不同的地方实例化线程并不是很优雅。这就是我在原始答案中发布 EDIT 的原因,它提供了另一种我从未尝试过的可能解决方案。
  • 哦,我明白了,谢谢。我有一个想法,我用它来代替。我只是检查了我的精灵是否已经存在,如果确实存在,那么也不要再次创建线程和精灵。好的,你的方式可能会更好,但我的方式目前正在工作,因此现在工作量减少了......虽然你确实帮助我尝试并激发了这个解决方案。谢谢你的帮助。打勾。
猜你喜欢
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
相关资源
最近更新 更多