90分钟学会Flex for Android






4.93/5 (18投票s)
在本教程中,您将使用 Flash Builder “Burrito” 和 Flex “Hero” 为 Android 设备构建一个简单但功能齐全的员工目录应用程序。“Burrito” 是 Flash Builder 下一版本的代号,“Hero” 是 Flex SDK 下一版本的代号。
概述
您无需 Android 设备即可完成本教程:您可以使用 Flash Builder Burrito 中提供的简单模拟器来运行和调试应用程序。
员工目录应用程序允许您
- 搜索员工
- 查看员工详情
- 在组织结构图中上下导航
- 致电、发短信和发送电子邮件给员工
开始之前
- 下载并安装 Flash Builder Burrito。Flash Builder Burrito 可在此处获取: http://labs.adobe.com/technologies/flashbuilder_burrito
- 从 http://coenraets.org/flexandroid90/FlexAndroid90Minutes.zip 下载 FlexAndroid90Minutes.zip,并将该文件解压缩到文件系统中的任意位置。
第一部分:创建基础移动应用程序
在本节中,您将构建一个显示员工列表的简单移动应用程序。
步骤 1:创建 Flex 移动项目
- 在 Flash Builder 菜单中选择 文件 > 新建 > Flex 移动项目。
- 在“项目位置”选项卡中,将项目名称指定为 EmployeeDirectory,然后单击“下一步”。
- 在“移动设置”选项卡中,保留默认值,然后单击“完成”。
- 将刚解压缩的 FlexAndroid90Minutes 文件夹中的 assets 目录复制并粘贴到 EmployeeDirectory 项目的 src 目录中。
步骤 2:编写应用程序代码
- 打开 EmployeeDirectory.mxml
- 注意根节点:MobileApplication
- 注意 MobileApplication 的 firstView 属性,它引用了 EmployeeDirectoryHome
- 打开 EmployeeDirectoryHome.mxml 并按如下方式实现 View
<?xml version="1.0" encoding="utf-8"?> <s:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" title="Home" creationComplete="srv.send()"> <fx:Declarations> <s:HTTPService id="srv" url="assets/employees.xml"/> </fx:Declarations> <s:List id="list" top="0" bottom="0" left="0" right="0" dataProvider="{srv.lastResult.list.employee}" labelField="lastName"/> </s:View>
注释
- 确保在 EmployeeDirectoryHome.mxml 中实现此代码,而不是在 EmployeeDirectory.mxml 中。
- 不要忘记为视图添加 creationComplete 事件。
步骤 3:运行应用程序
- 右键单击 EmployeeDirectory.mxml 中的任意位置,然后选择“运行方式”>“移动应用程序”。
- 选择“在桌面”并选择一个要模拟的设备。例如,Google Nexus One。
- 单击“运行”并测试应用程序。应用程序应如下所示
第二部分:使用移动项渲染器
在本节中,您将为员工列表定义一个移动项渲染器。
步骤
- 打开 EmployeeDirectoryHome.mxml 并为 List 定义一个内联 itemRenderer。itemRenderer 在第一行显示员工的名字和姓氏,在第二行显示员工的职位。
<s:List id="list" top="0" bottom="0" left="0" right="0" dataProvider="{srv.lastResult.list.employee}"> <s:itemRenderer> <fx:Component> <s:MobileIconItemRenderer label="{data.firstName} {data.lastName}" messageField="title"/> </fx:Component> </s:itemRenderer> </s:List>
- 运行并测试应用程序。应用程序应如下所示
第三部分:视图之间的导航
在本节中,您将创建一个 EmployeeDetails 视图,该视图显示列表中所选员工的详细信息。您将学习如何在视图之间导航和传递信息。
步骤 1:创建 EmployeeDetails 视图
- 右键单击 EmployeeDirectory 项目中的 views 文件夹,然后选择“新建”>“MXML 组件”。将组件名称指定为 EmployeeDetails,然后单击“完成”。
- 按如下方式实现 EmployeeDetails
<?xml version="1.0" encoding="utf-8"?> <s:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" title="Employee Details"> <s:HGroup verticalAlign="middle" gap="12"> <s:Image source="assets/pics/{data.picture}"/> <s:VGroup> <s:Label text="{data.firstName} {data.lastName}"/> <s:Label text="{data.title}"/> <s:Label text="{data.department}"/> <s:Label text="{data.city}"/> </s:VGroup> </s:HGroup> </s:View>
步骤 2:打开详细信息视图
- 打开 EmployeeDirectoryHome.mxml 并为 List 提供一个 change 事件处理程序,该处理程序用于为所选员工打开详细信息视图。
<s:List id="list" top="0" bottom="0" left="0" right="0" dataProvider="{srv.lastResult.list.employee}" change="navigator.pushView(EmployeeDetails, list.selectedItem)"> <s:itemRenderer> <fx:Component> <s:MobileIconItemRenderer label="{data.firstName} {data.lastName}" messageField="title"/> </fx:Component> </s:itemRenderer> </s:List>
步骤 3:运行应用程序
在列表中选择一名员工:将为所选员工显示一名员工的详细信息视图。
![]() |
![]() |
第四部分:创建操作栏
在本节中,您将为员工目录提供一个操作栏。
- 您将为应用程序的所有视图提供一个“主页”按钮,用户可以单击该按钮返回应用程序的第一个视图。
- 您将为 EmployeeDirectoryHome 的操作栏提供搜索控件,用于搜索员工。
步骤 1:创建主页按钮
- 打开 EmployeeDirectory.mxml 并定义以下导航栏内容(在结束的 </s:MobileApplication> 标签之前)。
<s:navigationContent> <s:Button icon="@Embed('assets/home.png')" click="navigator.popToFirstView()"/> </s:navigationContent>
- 运行并测试应用程序。请注意,由于导航控件是在应用程序级别定义的,因此它被应用程序的所有视图共享。
![]() |
![]() |
步骤 2:创建搜索栏
- 打开 EmployeeDirectoryHome.mxml
- 在结束的 </fx:Declarations> 标签之后,添加以下 titleContent 和 actionContent 以创建搜索栏。
<s:titleContent> <s:TextInput id="key" width="100%"/> </s:titleContent> <s:actionContent> <s:Button icon="@Embed('assets/search.png')" click="srv.send()"/> </s:actionContent>
通过此初始实现,单击搜索按钮将返回所有员工,无论您在搜索字段中输入什么。您将在第六部分实现一个有效的搜索功能。
- 由于我们现在在用户单击搜索按钮时发送数据请求,因此请删除在 View 上定义的 creationComplete 事件处理程序。
- 运行并测试应用程序。
请注意,EmployeeDetails 和 EmployeeDirectoryHome 视图都继承了在 EmployeeDirectory.mxml 中定义的主页按钮。虽然通常为应用程序的所有视图都提供主页按钮是个好主意,但应用程序的主页视图带有主页按钮是多余的(并且可能令人困惑)。
步骤 3:删除 EmployeeDirectoryHome 中的主页按钮
- 打开 EmployeeDirectoryHome.mxml 并在 <s:titleContent> 标签之前添加一个空的 navigationContent 标签。
<s:navigationContent/>
- 运行并测试应用程序。
请注意,当您打开一名员工的详细信息视图,然后使用设备的后退按钮(或应用程序的主页按钮)返回列表时,列表为空。这是因为当另一个视图变为活动状态时,之前活动的视图会自动销毁。当您单击后退按钮时,之前的视图实际上会被重新实例化。
步骤 4:持久化搜索结果
尽管视图在变得不活动时会被销毁,但其“data”属性会得到持久化,并在视图重新实例化时重新分配。
要持久化搜索结果并利用 data 属性
- 向 HTTPService 添加一个 result 事件处理程序,在该处理程序中,您将 HTTPService 调用的 lastResult 分配给视图的 data 属性。
<s:HTTPService id="srv" url="assets/employees.xml" result="data=srv.lastResult.list.employee"/>
- 将 List 绑定到视图的 data 属性。
<s:List id="list" top="0" bottom="0" left="0" right="0" dataProvider="{data}" change="navigator.pushView(EmployeeDetails, list.selectedItem)"> <s:itemRenderer> <fx:Component> <s:MobileIconItemRenderer label="{data.firstName} {data.lastName}" messageField="title"/> </fx:Component> </s:itemRenderer> </s:List>
- 运行并测试应用程序。
第五部分:集成设备功能
在本节中,您将允许用户在应用程序中致电、发短信或发送电子邮件给员工。
步骤 1:显示操作列表
- 在 EmployeeDetails.mxml 中,在 <s:HGoup> 开始标签之前添加一个 <fx:Script> 块。
<fx:Script> <![CDATA[ ]]> </fx:Script>
- 在新 <fx:Script> 块中,定义一个可绑定的 ArrayCollection 来保存所选员工可用操作的列表。
[Bindable] protected var actions:ArrayCollection;
注意:为使此代码编译成功,请确保导入 ArrayCollection 类:import mx.collections.ArrayCollection; - 定义以下嵌入式图标。您将在操作列表项渲染器中使用它们。
[Embed("assets/sms.png")] private var smsIcon:Class; [Embed("assets/phone.png")] private var phoneIcon:Class; [Embed("assets/mail.png")] private var mailIcon:Class;
- 重写视图的“data”属性的 setter,以便根据可用数据填充操作列表,其中包含员工可用的操作。例如,只有当移动电话号码可用时,才应向用户显示“SMS”操作。
override public function set data(value:Object):void { super.data = value; actions = new ArrayCollection(); if (data.officePhone) { actions.addItem({type: "tel", name: "Call office", details: data.officePhone, icon:phoneIcon}); } if (data.cellPhone) { actions.addItem({type: "tel", name: "Call mobile", details: data.cellPhone, icon:phoneIcon}); actions.addItem({type: "sms", name: "SMS", details: data.cellPhone, icon:smsIcon}); } if (data.email) { actions.addItem({type: "mailto", name: "Email", details: data.email, icon:mailIcon}); } }
- 显示操作列表:在结束的 </s:HGroup> 标签下方,添加一个绑定到 actions 列表的 List 组件。
<s:List id="list" dataProvider="{actions}" top="160" left="0" right="0" bottom="0"> <s:itemRenderer> <fx:Component> <s:MobileIconItemRenderer paddingTop="8" paddingBottom="8" verticalGap="6" labelField="name" messageField="details" decoratorClass="{data.icon}"/> </fx:Component> </s:itemRenderer> </s:List>
- 运行并测试应用程序。当您在列表中选择一名员工时,您应该会看到该员工可用的操作列表。操作尚不能正常工作。您将在下一步使其正常工作。
步骤 2:触发操作
- 向 List 添加一个 change 事件处理程序。
<s:List id="list" dataProvider="{actions}" top="160" left="0" right="0" bottom="0" change="list_changeHandler(event)"> <s:itemRenderer> <fx:Component> <s:MobileIconItemRenderer paddingTop="8" paddingBottom="8" verticalGap="6" labelField="name" messageField="details" decoratorClass="{data.icon}"/> </fx:Component> </s:itemRenderer> </s:List>
- 按如下方式实现 list_changeHandler。
protected function list_changeHandler(event:IndexChangeEvent):void { var action:Object = list.selectedItem; switch (action.type) { case "tel": navigateToURL(new URLRequest("tel:"+action.details)); break; case "sms": navigateToURL(new URLRequest("sms:"+action.details)); break; case "mailto": navigateToURL(new URLRequest("mailto:"+action.details)); break; } }
注意:为使此代码编译成功,请确保导入 spark.events.IndexChangeEvent(而不是 mx.events.IndexChangedEvent)。
import spark.events.IndexChangeEvent;
- 运行并测试应用程序。
第六部分:使用 RemoteObject
在本节中,您将使搜索功能正常工作。您将用一个提供 findByName 方法的 RemoteObject 替换 HTTPService。为了方便起见,RemoteObject 已托管在云端,因此您无需在自己的基础架构中部署任何内容。
当然,您也可以使用 HTTPService 实现搜索功能。我们切换到 RemoteObject 的原因是为了尝试不同的数据访问策略。
如果您对使用 RemoteObject 不感兴趣,可以直接跳到第七部分。
步骤
- 打开 EmployeeDirectoryHome.mxml。用如下定义的 RemoteObject 替换 HTTPService:
<s:RemoteObject id="srv" destination="employeeService" endpoint="http://flex.org:8080/extras/messagebroker/amf" result="data=srv.findByName.lastResult"/>
- 修改搜索按钮的 click 事件处理程序:使用 RemoteObject 的 findByName 方法查找与用户输入的搜索关键字匹配的员工。
<s:Button icon="@Embed('assets/search.png')" click="srv.findByName(key.text)"/>
- 运行并测试应用程序:在搜索字段中输入几个字符,然后单击搜索按钮以查看匹配的员工列表。
第七部分:使用本地 SQLite 数据库
在本节中,您将更改应用程序的数据访问逻辑:您将使用设备上可用的 SQLite 数据库来访问数据,而不是使用 RemoteObject(或 HTTPService)。
步骤
- 将 model 目录从 FlexAndroid90Minutes 文件夹复制并粘贴到 EmployeeDirectory 项目的 src 目录中。
- 探索 EmployeeDAO 和 Employee 类的源代码。
- EmployeeDAO 类提供了数据访问对象模式的基本实现:它封装了创建、更新和删除员工的数据访问逻辑。如果数据库中不存在员工表,EmployeeDAO 还包含一些逻辑来创建该表并用示例数据填充它。
- Employee 是一个基本的值对象,它还提供了某些惰性加载逻辑,以根据需要加载员工的经理和直接下属。
- 在 EmployeeDirectoryHome.mxml 中,用 EmployeeDAO 的实例替换 RemoteObject(或者如果您没有完成第六部分,则替换 HTTPService)。
<model:EmployeeDAO id="srv"/>
注意:确保在 mxml 文档顶部的 View 定义中绑定了 model 命名空间。
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" title="Home" xmlns:model="model.*">
- 相应地修改搜索按钮的 click 事件处理程序。
<s:Button icon="@Embed('assets/search.png')" click="data=srv.findByName(key.text)"/>
请注意,在这种情况下,我们可以直接将 findByName 函数的返回值分配给 data,因为 EmployeeDAO 使用了数据库访问 API 的同步版本。
- 打开 EmployeeDirectory-app.xml,然后向下滚动到文档的末尾。在 manifest 标签内(紧跟在 android.permission.INTERNET 权限之后)添加以下权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- 运行并测试应用程序。
第八部分:导航组织结构图
在本节中,您将向员工详细信息视图添加“查看经理”和“查看直接下属”操作,以便用户可以上下导航组织结构图。
步骤 1:创建 DirectReports 视图
- 右键单击 EmployeeDirectory 项目中的 views 文件夹,然后选择“新建”>“MXML 组件”。将组件名称指定为 DirectReports,然后单击“完成”。
- 按如下方式实现 DirectReports.mxml。
<?xml version="1.0" encoding="utf-8"?> <s:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" title="Direct Reports"> <s:List id="list" top="0" bottom="0" left="0" right="0" dataProvider="{data.directReports}" change="navigator.pushView(EmployeeDetails, list.selectedItem)"> <s:itemRenderer> <fx:Component> <s:MobileIconItemRenderer label="{data.firstName} {data.lastName}" messageField="title"/> </fx:Component> </s:itemRenderer> </s:List> </s:View>
步骤 2:添加导航组织结构图的操作
- 在 EmployeeDetails.mxml 中,向 set data 函数添加两个可能的操作。
if (data.manager) { actions.addItem({type: "employee", name: "View manager", details: data.manager.firstName + " " + data.manager.lastName, employee: data.manager}); } if (data.directReports && data.directReports.length > 0) { actions.addItem({type: "reports", name: "View direct reports", details: "(" + data.directReports.length + ")", employee: data}); }
- 在 List change 事件处理程序中,添加两个 case 语句以触发相应的操作。
case "employee": navigator.pushView(EmployeeDetails, action.employee); break; case "reports": navigator.pushView(DirectReports, action.employee); break;
步骤 3:运行应用程序
- 选择一名有经理的员工,然后单击“查看经理”操作。
- 选择一名有直接下属的员工,然后单击“查看直接下属”操作。
![]() |
![]() |
![]() |