Lua/Solar2d循环更新文本时界面不实时刷新的解决方法
问题原因
你遇到的UI不刷新问题本质是阻塞主线程导致渲染流程被抢占:
- 你所用的2D界面引擎(Solar2D/Corona SDK)采用单线程事件循环模型,主线程需要跑完当前所有同步执行的逻辑代码后,才会进入下一帧的渲染流程,把UI属性的变化绘制到屏幕上。
- 你实现的
sleep是忙等阻塞函数,通过空循环占满CPU时间片,完全不让出执行权;两层while循环连续执行的整个过程中,渲染管线始终拿不到运行机会。 - 你在循环内修改
text.text只是更新了文本对象的内存属性,控制台打印可以直接读取内存值所以显示正常,但这些属性变化要等所有循环执行完、主线程走到渲染步骤时才会被同步到屏幕上,因此会出现最后一次性刷新的现象。
解决方向
- 立刻删除忙等实现的阻塞式
sleep函数,永远不要在GUI主线程编写空转阻塞的逻辑,否则不仅会卡住UI,还会占满CPU导致应用卡顿。 - 使用引擎自带的非阻塞定时器API
timer.performWithDelay实现计时逻辑,该API会将更新回调挂载到引擎的事件循环中,每到指定间隔才执行回调,不会阻塞渲染流程。 - 额外注意:你代码中
text:setFillColor(0,0,256)的蓝色通道值超出了0-255的合法范围,建议修正为255。
修正后的可运行代码如下:
local function watch(mode, it, text, texty, para) local text = display.newText(scene.view, "", display.contentCenterX, 200, nativeSystemFont, 60) text:setFillColor(0,0,255) local round = 0 -- 外层循环轮次计数 local sec = 0 local goal = 20 local timerHandle -- 提前声明定时器句柄 text.text = sec -- 每秒触发一次的计时回调 local function tick() -- 所有轮次执行完成后终止定时器 if round >= it then timer.cancel(timerHandle) return end sec = sec + 1 text.text = sec print(text.text) -- 当前轮次计时达到目标值,重置秒数、轮次+1 if sec >= goal then sec = 0 round = round + 1 end end -- 每1000毫秒(1秒)执行一次tick,第三个参数0表示无限重复 timerHandle = timer.performWithDelay(1000, tick, 0) end
注:如果页面/场景被销毁,需要主动调用
timer.cancel(timerHandle)取消定时器,避免内存泄漏和野指针报错。
内容的提问来源于stack exchange,提问作者Nicholas O'Neal
相关产品推荐
相关产品推荐

