onPause无法停止线程、onResume无法恢复执行的Android游戏开发问题
乒乓球游戏后台仍运行问题解决方案
问题根因
你的代码存在三个核心问题导致退后台游戏未停止:
- 每次调用
start()方法都会创建全新的GameThread实例,且没有持有旧线程的引用,容易出现多个线程并行运行的情况,仅修改gameOn变量无法保证所有线程都停止。 Activity生命周期方法中逻辑错误:onPause仅修改gameOn没有做线程退出处理,onResume仅修改gameOn没有重启线程,生命周期状态和线程运行状态不匹配。onSizeChanged可能被多次触发(如View布局调整、配置变化等),每次都会调用start()创建新线程,加剧多线程并行问题。
修复步骤
1. 修改GameBoard代码,添加线程持有逻辑
更新后的GameBoard代码如下:
class GameBoard : View { @Volatile var gameOn = false // 添加线程引用成员变量 private var currentGameThread: GameThread? = null // 添加宽高初始化标记,避免onSizeChanged重复触发start private var isSizeInitialized = false //several member variables fun start(){ // 先停止已有线程,避免多线程并行 stop() gameOn = true currentGameThread = GameThread() currentGameThread?.start() } fun stop(){ gameOn = false // 中断线程并等待退出,避免线程残留 currentGameThread?.interrupt() try { // 最多等待1秒,避免阻塞主线程导致ANR currentGameThread?.join(1000) } catch (e: InterruptedException) { // 忽略中断异常 } currentGameThread = null } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) mWidth = width mHeight = height cxBall = (Random.nextInt(1, mWidth)).toFloat() cyBall = (mHeight/6).toFloat() cxPaddle = (width/2 - PADDLE_WIDTH/2).toFloat() paintScoreText.textSize = height / 20f paintHighScoreText.textSize = height / 20f // 仅第一次初始化宽高时调用start,避免重复触发 if (!isSizeInitialized) { isSizeInitialized = true start() } } inner class GameThread : Thread() { override fun run() { while (gameOn) { //do some processes // 如果有Thread.sleep逻辑,捕获中断异常直接退出循环 try { // 你的游戏逻辑,包括sleep代码 if (ballOutsideRange) { gameOn = false } } catch (e: InterruptedException) { break } } } } }
2. 修改MainActivity生命周期逻辑
更新后的MainActivity代码如下:
class MainActivity : AppCompatActivity() { private lateinit var mGameBoard:GameBoard override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_MainActivity) this.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT mGameBoard = GameBoard(this.applicationContext) mGameBoard.setMode("easy") } override fun onResume() { super.onResume() // 调用start方法重启游戏线程,不要直接修改gameOn mGameBoard.start() } override fun onPause() { super.onPause() // 调用stop方法完全停止游戏线程 mGameBoard.stop() } }
补充说明
如果你的游戏逻辑中有休眠逻辑,捕获InterruptedException后直接break退出循环即可,确保线程能快速响应停止请求,不会残留运行。
内容的提问来源于stack exchange,提问作者Subi
相关产品推荐
相关产品推荐

