在onResume/onPause中重新启动/暂停线程

7
我有一个使用 SurfaceView 实现的游戏,在屏幕上显示对象。 我有一个线程,它会定时绘制 SurfaceView 到屏幕上。 游戏已经完全运行。 不过,每当游戏被打断时,需要有一个暂停功能。 我知道需要操纵 onResume 和 onPause。
但是我做不对。错误指向我开始线程的 surfaceCreated,告诉我线程已经启动了。我尝试在 onResume 和 onPause 上分别使用 resume 和 suspend,但没有任何变化。
我该如何实现这个功能? 我已经处理好了使用文件 I/O 处理保存对象位置的内容。
提前感谢您的帮助。

可能是如何在Android中暂停/恢复线程?的重复问题。 - Wroclai
4个回答

3

这是我所做的:

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
           if (thread.getState() == Thread.State.TERMINATED){
              CreateThread(getHolder(),getContext());
           }
           thread.setRunning(true);
           thread.start();
    }
  • 在CreateThread中,您应该使用thread = new MyThread(...)创建线程;
  • 使用setRunning(boolean mRun)方法,通过布尔值来启动/停止run函数(我认为受到了LunarLander的启发);

如果想要正确使用onPause/onResume,请不要将线程使用的变量放在线程内部(如LunarLander所做的那样)。我建议您采用以下方式:

// Variables declarations

public MyGameThread CreateThread(...){
thread = new MyGameThread(holder, context, new Handler() {
// and so on....
});
}

当您通过onPause/onResume时,您的线程将被销毁并重新创建,但如果您将变量放在外面,您可以在之后继续使用它们。
如果您有重要的内容需要保留,请使用以下选项之一:
- SharedPreferences:将创建一个XML文件并保存本地变量,即使应用程序结束后也会持久存在。 - 如果您需要管理超过5-10个变量,则可以使用SQL数据库,因为在这种情况下使用前一个选项会很困难。

你能进一步扩展一下吗?我无法通过它进入。对于回复晚了,很抱歉。 - Cyril Horad
好的,开始学习这个博客:http://wonton-games.blogspot.com/2010/06/lunar-lander-resume-game-workaround.html 我在那里了解了很多关于“月球着陆器问题”的内容。之后,请带着详细的问题回来 ;) - Zappescu

2

实际上不建议自己停止线程,stop() 方法已经被弃用。最简单的解决方案是在线程的 run() 方法中使用一个标志位,在 while 循环中使用。当你需要 "停止" 线程时,只需将标志位设置为 false,线程将不再执行任何操作,但仍会继续运行。Android 将在需要时停止您的线程。希望这有所帮助。


那么,当我从onPause将运行标志设置为false时,如何重新启动正在运行的线程呢? - Cyril Horad
@ Cyril Horad,您的应用程序将只是启动另一个具有相同任务的线程。 - Egor
开始另一个线程吗?但那不会从头开始执行任务吗? - Cyril Horad
@ Cyril Horad,你应该保存所有需要恢复工作的信息,当然任务将从头开始,由你来恢复工作。 - Egor
我明白了。但是重新开始一个捆绑/文件的工作不会浪费时间吗? - Cyril Horad
@ Cyril Horad,即使如此,您也没有其他选择。当您的应用程序暂停时,系统不会存储任何信息,因此您必须自己处理。 - Egor

1

不了解您的代码的内部细节。

要“暂停”线程,您可以实现以下功能:

while(! this.isInterrupted())
    if(!paused)
    {
        ... Do something ...
    } else { try { Thread.sleep(100) } catch (InteruptedException ie) {} }

这取决于Do something是否使您的SurfaceView无效或以其他方式控制应用程序的进度。访问paused的方法应该允许您暂停和恢复线程,而不会被任何其他架构所困扰。


1

我不确定你在这个问题中是否有一个或两个线程,我假设有2个。当你调用onPause时,你需要做三件事:

1 - Save the state of the application (all game variables, states, etc)
2 - Kill the surfaceView by calling suspend.
3 - Kill the other thread (we'll call it Thread B).

我认为杀死线程B是你的问题。你想要中断线程并告诉它退出,否则当你调用onPause时,你的线程仍然会继续运行。然后,当你重新进入游戏时,线程将尝试再次创建,这就导致了问题。有两种正确终止线程的方法:

  • 在你的线程的while()循环中,有一个布尔值'run',while(run)将执行代码。当你将run更改为false时,线程退出。
  • 如果你的线程休眠(我假设它可能会这样做,因为它是一个游戏,并且将根据时间运行),捕获InterruptedException,然后在那里退出。当你想要终止线程时,你向线程抛出异常。

第一种方法是最简单的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接