|
|
做了个购物清单App后,我才真正搞懂App Inventor 2的变量
上个月教侄子学App开发,他一脸困惑:"变量不就是装东西的盒子吗?为什么我的App总是显示旧数据?"
这让我想起自己刚接触App Inventor 2时的困惑——全局变量、局部变量、初始化、取值设置,概念都听过,但真正写App时,还是会被"数据不更新""变量作用域混乱"这些问题反复折磨。
干脆用一个购物清单App的实际开发过程,把变量那点事彻底讲透。
需求分析
侄子想要一个简单的购物清单:
- 能添加商品名称和数量
- 能查看当前清单
- 能删除已购买的物品
- 关闭App再打开,数据还在
看似简单,但每一条背后都涉及变量的核心知识点。
技术方案
- 存储商品列表 → 全局变量 → 整个App共享
- 临时输入暂存 → 局部变量 → 过程内部使用
- 商品计数 → 全局变量 → 跨屏访问
- 持久化存储 → TinyDB + 全局变量 → 配合使用
关键实现
Step 1:初始化全局变量——构建数据地基
拖出一个 initialize global 积木:
initialize global shoppingList to [create empty list]
initialize global totalCount to 0
关键理解:全局变量在App启动时就被创建,所有Screen、所有过程都能访问它。这就是为什么它叫"全局"——作用域覆盖整个App。
侄子一开始犯了个经典错误:在按钮点击事件里初始化全局变量。结果每点一次按钮,列表就被清空一次。全局变量的初始化只执行一次,这是和局部变量最大的区别之一。
Step 2:局部变量——过程中的临时工
添加商品时,需要先暂存用户输入,验证后再写入列表:
when ButtonAdd.Click:
initialize local itemName to TextBoxName.Text
initialize local itemQty to TextBoxQty.Text
if itemName != "" then:
add items to list: global shoppingList
set global totalCount to totalCount + 1
关键理解:initialize local 创建的变量只在当前过程(Procedure)或事件(Event)内有效。执行块(do)适合执行操作,返回值块(return)适合计算后返回结果。
侄子问:"为什么不直接用 TextBoxName.Text?"
好问题。用一个局部变量 itemName 暂存,好处是:
1. 代码更清晰——名字比 TextBoxName.Text 好读
2. 性能更好——避免反复访问组件属性
3. 便于调试——一眼看到中间值
Step 3:取值与设置——变量的日常操作
查看清单时,遍历全局变量:
when ButtonView.Click:
initialize local displayText to ""
for each item in global shoppingList:
set displayText to displayText & item
set LabelDisplay.Text to displayText
这里有两个核心积木:
- get(取值):读取变量的当前值
- set(设置值):给变量赋新值
看似简单,但有个陷阱:全局变量用 set 会直接覆盖。如果你想累加,必须写成 set global X to get X + 1,而不是 set global X to 1。
Step 4:持久化——变量的"存档"机制
全局变量在App关闭后就消失了。要实现"关闭再打开数据还在",需要TinyDB配合:
when Screen1.Initialize:
set global shoppingList to TinyDB1.GetValue(tag: "shoppingList", default: create empty list)
set global totalCount to TinyDB1.GetValue(tag: "count", default: 0)
when ButtonSave.Click:
call TinyDB1.StoreValue(tag: "shoppingList", value: global shoppingList)
call TinyDB1.StoreValue(tag: "count", value: global totalCount)
模式:Screen初始化时从TinyDB加载 → 运行中用全局变量操作 → 退出前存回TinyDB。
踩过的坑
坑1:局部变量在过程外访问
侄子试图在按钮B里访问按钮A中创建的局部变量。当然失败——局部变量的生命周期仅限于声明它的块内。
解法:需要跨事件共享的数据,必须用全局变量。
坑2:变量命名冲突
同时用了 count 做全局变量名和局部变量名,结果全局变量的值被局部变量"遮蔽"。
解法:全局变量统一加前缀 g_(如 g_count),或用描述性名称(如 totalItemCount)。
坑3:初始化顺序
在 Screen.Initialize 里先用了变量,再初始化它。变量还没创建就被读取,返回空值。
解法:所有全局变量的初始化放在Screen.Initialize的最前面。
最终效果
侄子的购物清单App成功运行:
- 添加商品(局部变量暂存 + 全局列表追加)
- 查看清单(遍历全局变量 + 字符串拼接)
- 持久化(TinyDB + 全局变量配合)
- 商品计数(全局变量累加)
他在学校展示时,同学都惊讶"这么简单的积木能做出真正好用的App"。
复盘感悟
变量是编程的地基。App Inventor 2把变量简化为5种积木块——初始化全局、初始化局部(do)、初始化局部(return)、取值、设置值——看起来简单,但每个都有其使用场景:
- 全局变量:App级共享数据,初始化一次
- 局部变量(do):过程中的临时操作,用完即弃
- 局部变量(return):过程中的临时计算,返回结果
- get/set:读写变量的唯一方式
记住一个原则:能用局部变量就不用全局变量。作用域越小,出bug的概率越低。
更多App Inventor 2教程和实战案例,欢迎访问 App Inventor 2 中文网
加入我们的技术社区:清泛IT社区 -- 与更多开发者一起交流 |
|