启动while循环后App卡顿、界面无响应问题求助
问题分析与解决方案
核心问题
- 主线程被阻塞:直接在UI线程调用
gameloop.loop()的死循环会完全占用主线程,导致Compose无法更新UI,界面切换、按钮状态同步全部失效。 - 无帧率控制:循环无间隔执行会导致CPU占用过高,同时玩家移动逻辑执行速度不受控,游戏逻辑异常。
- 线程安全问题:UI线程更新的按钮状态(
jumpButton等),后台线程读取时可能无法获取最新值。
修复方案
1. 重构游戏循环至后台线程并添加帧率控制
修改Gameloop类,将循环移至后台线程,并固定帧率避免资源浪费:
package com.example.jumpking.ui.theme class Gameloop( private val game: Game ) { var jumpPower = 1f var jumpY = 0f private val targetFps = 60 private val frameTimeNs = 1_000_000_000 / targetFps fun startLoop() { Thread { while (Application.gamestatus == Application.GAMESTATUS.RUNNING) { val startTime = System.nanoTime() // 同步访问游戏状态,保证线程安全 synchronized(game) { if (game.jumpButton) { game.player.move(0f, jumpPower) } if (game.leftButton && !game.rightButton) { game.player.move(-jumpPower, 0f) } if (!game.leftButton && game.rightButton) { game.player.move(jumpPower, 0f) } } // 计算帧间隔,控制帧率 val elapsedTime = System.nanoTime() - startTime val sleepTime = frameTimeNs - elapsedTime if (sleepTime > 0) { Thread.sleep(sleepTime / 1_000_000, (sleepTime % 1_000_000).toInt()) } } }.start() } }
2. 在Compose生命周期内启动游戏循环
修改MainActivity,使用LaunchedEffect在游戏状态激活时启动循环,避免阻塞UI线程:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { JumpKingTheme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { val gameclass = Game() val gameloop = Gameloop(gameclass) when (Application.currentState) { Application.GAMESTATE.SCOREBOARD -> ScoreboardScreen() Application.GAMESTATE.PLAYING -> { gameclass.GameScreen(gameloop) // 仅在进入游戏状态时启动循环 LaunchedEffect(Unit) { gameloop.startLoop() } } Application.GAMESTATE.MENU -> MenuScreen() } } } } } }
额外优化建议
- 将游戏中的按钮状态变量(
jumpButton、leftButton等)标记为@Volatile,或使用线程安全的状态容器,进一步保障线程间状态同步。 - 若使用Compose的状态管理(如
MutableState),可直接利用其线程安全特性,替代synchronized块。
内容的提问来源于stack exchange,提问作者Teodor Nyman
相关产品推荐
相关产品推荐

