跳到教程内容
教程首页
App Inventor 2 教程 投票App
准备开始
动手创造 · PROJECT LAB

投票App

准备探索你的新作品
0%
★★☆ 项目难度每一步,都离作品更近

先了解你将做出什么

应用介绍

这次做一个最小但完整的多人投票:所有用户看到同一个问题,点击“赞成”或“反对”后,云数据库 会把最新票数推给所有在线设备。重点不是画复杂图表,而是理解云数据“发起请求、等待回调、实时同步”的流程。

教程主图

投票App教程(难度系数:★★☆)

准备组件

组件类型 组件名称 关键设置
标签 标签_问题 显示投票问题
按钮 按钮_是 文本:赞成
按钮 按钮_否 文本:反对
标签 标签_是 显示赞成票数
标签 标签_否 显示反对票数
标签 标签_状态 显示同步状态
按钮 按钮_重置 管理员重置
云数据库 云数据库1 非可视组件

云数据库 使用两个标签保存列表:yes 存赞成票,no 存反对票。列表长度就是票数,列表内容本身不重要。

统一更新票数

云数据库 的 GotValueDataChanged 都会带回标签和值。把两种事件都交给同一个过程, 可以避免写两份几乎一样的计数逻辑。

global 赞成票 = []
global 反对票 = []

procedure 更新票数(tag, value) {
  if tag = "yes" {
    赞成票 = value
  } else if tag = "no" {
    反对票 = value
  }
  标签_是.Text = join("赞成:", length(赞成票))
  标签_否.Text = join("反对:", length(反对票))
}

when Screen1.Initialize() {
  云数据库1.GetValue("yes", [])
  云数据库1.GetValue("no", [])
  标签_状态.Text = "正在读取票数……"
}

when 云数据库1.GotValue(tag, value) {
  更新票数(tag, value)
  标签_状态.Text = "票数已更新"
}

when 云数据库1.DataChanged(tag, value) {
  更新票数(tag, value)
}

GetValue 不会立刻返回列表,结果在 GotValue 事件里;其他用户投票时,本机则会收到 DataChanged。 这就是云数据库和本地 微数据库 最大的使用差别。

记录赞成和反对

AppendValueToList 向云端列表追加一项。按钮禁用是为了防止同一台设备连续点击多次;测试时可以暂时不禁用, 但正式使用时应保留这两行。它只能限制一台设备,不能替代服务端的身份校验。

when 按钮_是.Click() {
  云数据库1.AppendValueToList("yes", "yes")
  按钮_是.Enabled = false
  按钮_否.Enabled = false
  标签_状态.Text = "你的赞成票已提交"
}

when 按钮_否.Click() {
  云数据库1.AppendValueToList("no", "no")
  按钮_是.Enabled = false
  按钮_否.Enabled = false
  标签_状态.Text = "你的反对票已提交"
}

清空测试数据

重置按钮只给管理员使用。清空两个标签后把本地列表也重置,并重新启用投票按钮;实际发布时应给这个按钮加密码或移出普通用户界面。

when 按钮_重置.Click() {
  云数据库1.ClearTag("yes")
  云数据库1.ClearTag("no")
  赞成票 = []
  反对票 = []
  按钮_是.Enabled = true
  按钮_否.Enabled = true
  标签_状态.Text = "投票已重置"
  更新票数("yes", 赞成票)
}

开始测试

  1. 两台设备连接同一个 云数据库 项目,分别投一票,双方票数是否都更新。
  2. 点击一次后按钮是否禁用,重新打开 App 后能否读到已有票数。
  3. 测试网络暂时断开时,是否给用户明确的连接失败提示。
  4. 点击重置后两边票数是否回到 0。
  5. 管理员按钮是否没有直接暴露给普通投票者。

剩余工作

可以增加百分比、进度条或 Chart 图表;也可以给每个投票者生成唯一身份,防止同一人重复投票。 真实项目还要考虑 云数据库 权限、隐私和并发写入,不能只靠按钮禁用保证公平。