本系列第 3/8 课,建议 45–60 分钟(估算)。先完成上一课。
这课解决什么
Clock 的 Timer 是刷新机会,不保证每次恰好间隔一秒。保存截止毫秒,每次用截止减当前时刻求剩余;ceil 让不足一秒仍显示一秒,max 防止负数。
先预测,再运行
原来还有 120 秒,下一次回调晚了 12.345 秒,应该显示多少?
先记下自己的答案,运行起始工程与完成工程比较;答案见文末。
开始实战
以上一课完成工程为起点,先导入并运行,再另存为本课作业。
完成工程可以查看答案;独立作业请保留自己的修改。
新增或调整的组件
| 实例名 | 组件 | 本课配置 |
|---|---|---|
标签_标题 |
标签 | Width=Fill parent;FontSize=24;TextColor=#183153;Text=专注学习 · 第 3课 |
计时器1 |
计时器 | TimerEnabled=False;TimerAlwaysFires=False;TimerInterval=1000 |
逐步搭建
- 增加计时器1,TimerEnabled=false、TimerInterval=1000、TimerAlwaysFires=false。
- 开始时把截止设为 SystemTime()+剩余×1000,并启用 Timer。
- Timer 中按截止计算剩余;为零时先改完成状态,再关闭计时器。
- 用 1 分钟观察到期,比较每次减 1 的版本;刷新频率改快不会改变实际截止时刻。

图来自本课最终工程执行积木后的状态,为 HTML 近似预览;不是手机截图。
核心积木与数据流
下面是本课完成工程中的核心代码,包含所需全局变量和过程。可在块图中追踪数值,再回到工程对照完整事件;合并到已有工程时,同名事件合并处理。
global 剩余 = 0
global 截止 = 0
global 状态 = "待开始"
global 任务 = ""
when 计时器1.Timer() {
if 状态 = "运行" {
剩余 = max(0, ceil((截止 - 计时器1.SystemTime()) / 1000))
if 剩余 = 0 {
状态 = "完成"
计时器1.TimerEnabled = false
}
标签_剩余.Text = join(剩余, " 秒")
标签_状态.Text = join(状态, ":", 任务)
}
}
中途检查与排错
本课以下控制与数据流已执行最终归档中的真实积木检查。请在伴侣或安装的 APK 中按相同场景操作,记录实际结果;自动检查通过不代表手机已实测。
- 拒绝空任务。
- 非数字、非正数、上限、小数拒绝。
- 2分钟等于120秒。
- 延迟回调按实际时间计算。
- 到期与重复计时回调。
排查时先确定出错的是输入、状态、数据读取还是显示;用标签暂时显示关键值,每次只改变一个条件。
本阶段尚未加入数据保存,关闭应用会丢失任务;计时器用于前台刷新,不是系统后台闹钟。
两个理解题与独立改造
- 原来还有 120 秒,下一次回调晚了 12.345 秒,应该显示多少?
- TimerInterval 改为 100 毫秒后,1 分钟任务会缩短十倍吗?
独立改造: 增加 mm:ss 显示,秒数不足两位时补零。
先完成自己的工程,再对照答案。检查成功路径,也检查空数据、重复操作和取消;写出你改动的规则。
查看预测与练习参考答案
预测: ceil(120−12.345)=108 秒。简单每次减 1 会错误显示 119 秒。
追踪: 不会。截止固定,频率只改变界面刷新次数;SystemTime 给出毫秒。
改造思路: 分钟=floor(剩余/60),秒=剩余%60;秒<10 时 join(“0”,秒)。保留数值变量,不从显示文本反算。
完成与下一步
保存自己的工程并导出 .aia;给文件命名以区分本课作业和参考源码。请用自己的话解释本课知识,并展示一次失败输入的处理。
扫码添加客服咨询