友情提示:380元/半年,儿童学编程,就上码丁实验室。

如你所见,应用包含了对事件的处理,以及处理过程中的决策。这些处理过程构成了程序的基础,但只有这些是远远不够的,构成程序的另一个非常重要的基础就是数据——程序所要处理的信息。程序中的数据可以划分为简单数据和复杂数据两种类型。
简单数据只占有一个单独的存储空间(如数字变量、字符串变量、逻辑变量等),像游戏中分数这样的数据就属于简单数据。不过只有少量应用中只涉及简单数据,更普遍的情况是,大多数应用中都会使用复杂数据。
复杂数据是由多个甚至多种简单数据以某种特定结构组织起来的数据列表,必须像设计应用的功能一样,非常细心地组织这些数据。

我们将学习如何针对列表数据编程,然后再探索一种更为复杂的结构化数据——包含列表的列表,并在问答类应用中实现多选答案功能。
许多应用中都会涉及对列表的处理,如Facebook中的好友列表及状态列表,问答类应用中的问题及答案列表,游戏中的角色列表以及最高历史记录列表,等等。
在App Inventor中,用变量来定义列表数据,但与简单数据不同的是,列表数据的存储空间不再只是单一的存储单元,而是一组相互关联的存储单元。对于静态数据列表,可以使用“列表”块来设置列表变量的值,如图19-1所示,电话簿列表中包含了3个电话号码;对于动态数据的列表,可以使用“空列表”块来设置列表变量的初始值。

创建列表变量
在编程视图中,使用“声明全局变量”块来创建列表变量,并用列表块来初始化该列表变量。在内置块的列表类分组中,可以找到列表块。默认情况下,列表块有两个插槽, 点击其左上角的蓝色标记,可以扩展出任意多个插槽,以便向列表中添加更多的项,如图19-2所示。

选择列表项
在应用运行过程中,需要从列表中选取指定的项。例如,在问答类应用中,用户要浏览每一个问题;在随机拨打电话应用中,要选取某个电话号码。为了从列表中选取指定的项,需要引入“索引值”的概念。由于列表中数据的排列顺序是相对固定的,因此,一个列表项在列表中的位置与列表项本身是一一对应的,这个排列位置被称为该列表项的索引值,我们就使用这个索引值来访问指定的项。假设某个列表中有三个项,则这些项的索引值分别是1、2、3,我们就用这些数字以及选取列表项块来获取指定的列表项。如图19-3所示,我们选中的是电话簿列表中的第二项。

使用索引值遍历列表
在许多应用中,定义列表的目的是让用户可以遍历列表(逐个查看或操作每一个列表项)。第8章总统问答就是一个很好的例子:用户点击下一题按钮,程序从问题列表中选中并显示下一题。
前面例子中选中的是列表中的第二项,但是如何才能选中下一项呢?在遍历列表的过程中,每次选中的列表项不同,因此列表项对应的索引值也不同,即选中项在列表中的位置不同。因此,我们需要定义一个变量来表示这个位置,通常以索引值作为变量名,初始值通常设为1(列表中的第一个位置),如图19-4所示。


举例:遍历颜色列表
设想有这样一个应用,用户在粉刷房子前要选择涂料的颜色:在颜色列表中保存了若干种备选颜色,用户点击按钮,可以浏览列表中的颜色;每次点击,按钮的颜色都会变化;当用户查阅完全部颜色时,再重新回到第一种颜色。
例子中使用的是三原色,你也可以修改代码,替换成任何一组颜色。
第一步,定义一个颜色列表,并将列表项设置为某些颜色,如图19-6所示。

用户通过点击颜色按钮,浏览列表中的下一个颜色,此时,索引值递增,而按钮的背景颜色变为当前选中的颜色,如图19-7所示。

想象一下,下一次点击会出现什么情况?
被你说中了,程序会出错!索引值将变成4,程序试图在颜色列表中选择第四项,但列表中只有三个列表项,因此程序会出错,用户将在开发环境的编程视图中看到一段错误提示信息,如图19-8所示。


正如你所想象的,这些硬编码会让程序在短时间内变得混乱不堪,也会产生更多潜在的错误。事实上,在“粉刷房屋”应用的设计中,就在我们刚刚完成的程序中,还存在另外一处硬编码,你能找出是什么吗?
如果将颜色列表中的第一项由红色改为其他颜色,应用的运行结果就不再正确,除非你能记得在设计视图中修改颜色按钮背景颜色的初始值。消除这种硬编码的方法是,用代码将颜色按钮的初始值设定为颜色列表中的第一项,而不是某个特定的颜色。由于这一修改涉及程序启动时的行为,因此需要在Screen1的初始化事件处理程序中进行这一设定,如图19-10所示。

创建输入表单及动态数据
前面的“粉刷房屋”应用涉及一个静态列表:程序员(也就是你)定义了列表中的元素,且除非你亲自动手,没有人能修改这些列表项。然而,在多数情况下,应用中的列表是动态的:数据可能来源于最终用户的输入,也可能来源于数据库或网络信息源,因此列表的内容可能会随时改变。本节将讨论一个“随手记”应用:用户在应用中,通过表单输入笔记,并可浏览此前的笔记内容。
定义动态列表
像“随手记”这类应用,列表内容全部由用户输入,因此在应用开始运行时,要将列表变量设置为空列表,使用空列表块来定义列表的初始值,如图19-11所示。

当第一次启动应用时,笔记本列表是空的。当用户在表单中输入数据并点击“保存”按钮时,新的笔记内容将被添加到笔记本列表中。表单的设置非常简单,如图19-12所示。


显示列表
对用户来说,变量笔记本列表的内容是不可见的。还记得之前讲过,应用中的变量用来保存那些不需要被用户看到的信息。图19-13中的块实现了向笔记本列表添加新项的功能,但是,如果程序中没有添加显示列表内容的功能,用户是看不到任何反馈的。
要在用户界面中显示列表内容,最简单的方法莫过于将列表变量直接设置为标签的显示文本属性,就像显示数字和文本一样,如图19-14所示。


删除列表项
使用“删除列表项”块可以从列表中删除某一项,如图19-16所示。

列表选择框组件是一个用户界面组件,非常适合用来删除列表项。在默认状态下,列表选择框显示为一个关联按钮,当用户点击该按钮时,列表选择框会显示出所有的列表项,并允许用户选择其中的一项。当用户选中某一项后,就可以将该项删除掉。
列表选择框有两个关键事件:准备选择事件和完成选择事件。此外,列表选择框还有两个重要的属性:列表和选中项。如表19-1所示,只要理解了列表选择框的两个事件及两个属性,对该组件的编程就变得非常容易。
表19-1 列表选择框组件的两个关键事件及属性

当用户点击列表选择框的关联按钮时,触发准备选择事件。在准备选择事件处理程序中,可以设置列表选择框的列表属性,可以将列表属性设置为一个列表变量,以便用户可以从中进行选择。在“随手记”应用中,将列表属性设置为笔记本列表,如图19-17。


不过,在这个例子中,选择的目的是从列表中删除该项,而在删除列表项的块中,需要的参数是索引值(第几项),而不是具体的项。选中项属性中保存的是实际数据(一条笔记),并不是索引值,因此需要使用选中项索引值属性,它提供了选中项在列表中的索引值,可以直接用于删除列表项块,作为它的索引值参数,如图19-19所示。

列表中的列表
列表项可以是任何类型的数据,包括数字、文本、颜色、布尔值(真、假),也可以是列表本身。这是一种常见的数据结构。例如,一个列表的列表可以将第8章的“总统问答”应用转变为提供多选答案的应用。我们来重温一下“总统问答”中数据的基本结构:一个问题列表和一个答案列表,如图19-20所示。

为了提供多选答案,需要额外添加一个列表,为每个问题提供若干个可供选择的答案。将三个列表块放在一个外层的列表块中,来定义这个列表变量,如图19-21所示。

在“随手记”应用中,使用了一个列表选择框来显示可供选择的列表数据。假如索引值被命名为当前问题索引值,则准备选择事件的处理程序将如图19-22所示。



小结
几乎你能想到的每个应用中都会用到列表,所以理解列表的运行机制是编程的基础。本章探索了一种最常用的编程模式:使用索引值变量,从列表的第一项开始,通过变量的递增实现对每个列表项的逐一处理。如果能理解并在自己的程序中加以运用,那么你就成为一名真正的程序员了。
然后我们讲到了操作列表的其他方式,包括一个典型的表单,用户可以在其中添加、删除列表项。这种编程方式需要开发者具备更强的抽象能力,你要假想数据已经存在,毕竟在用户输入信息之前这些列表都是空的。如果你能理解这一点,你甚至可以考虑辞掉现在的日常工作了(在美国,软件工程师是高薪职业。在Glassdoor网站发布的2015年美国十大高薪职业中,软件架构师位列第三,软件开发经理位列第四,系统分析师位列第六。这些都是与软件技术相关的职业。Glassdoor是美国一家雇员或前雇员匿名评价老板及晒薪水的网站。——译者注)。
最后我们介绍了复杂的数据结构——列表的列表。这显然是一个不太容易理解的概念,但我们利用一些固定的数据对问题进行了探索:提供多选答案的问答类应用。如果你对此以及本章的其余部分都有所掌握,就来挑战一下我们的期末考试:使用列表的列表来创建一个应用,但要求使用动态数据!提示一下,你可以使用此前的例子——第10章的“出题”应用,但要扩展原有功能,允许用户在应用中自己提供多选答案。祝你好运!
在你思考如何处理这些列表时,要知道我们的探索还没有结束。在下一章中,我们将继续讨论并重点讲解另一个版本的列表循环:对列表中的每一项实施一系列的操作。