You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 01:54:03