原文地址:http://www.adobe.com/devnet/flex/articles/employee-directory-android-flex.html
在本教程中,您将使用Flash Builder “Burrito”和Flex SDK “Hero”构建一个简单但功能完备的适用于Android设备的员工目录应用程序。“Burrito”是Flash Builder的下一版本的代号,“Hero”是Flex SDK的下一版本的代号。
您不需要Android设备就可以完成本教程的学习。 您可以使用Flash Builder “Burrito”中提供的简单的模拟器来运行和调试应用程序。
这个Employee Directory应用程序可以让您进行以下操作:
- 1.搜索员工
- 2.查看员工详细信息
- 3.向上或向下浏览组织结构图
- 4.给员工打电话、发短信和发邮件
第一部分:创建一个基本的移动应用程序
在本章节中,您将会构建一个简单的移动应用程序,该程序会显示一个员工列表。
第一步:创建Flex Mobile项目
- 1.在Flash Builder菜单中选择File(文件) > New(新建) > Flex Mobile Project(Flex Mobile项目)。
- 2.在Project Location(项目位置)选项卡中,指定项目名称为EmployeeDirectory,然后点击Next(下一步)(参见图1)。
图1. 指定项目名称为EmployeeDirectory。
- 3.在Mobile Settings(移动设置)选项卡中,保留默认值并点击Finish(完成)(参见图2)。
图2. Mobile Settings(移动设置)选项卡
- 4.从您刚刚解压的FlexAndroidWorkshop文件夹中复制assets目录,然后将其粘贴到EmployeeDirectory项目的src目录中。
第二步:应用程序编码
- 1.打开EmployeeDirectory.mxml:
- 请注意根节点:MobileApplication
- 您会注意到MobileApplication的firstView属性引用了EmployeeDirectoryHome。
- 2.打开EmployeeDirectoryHome.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= "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 >
注:
- 1.请确保您是在EmployeeDirectoryHome.mxml中实现此代码,而不是EmployeeDirectory.mxml。
- 2.请不要忘记向该视图添加creationComplete事件。
第三步:运行应用程序
- 1.在EmployeeDirectory.mxml中右键点击任意地方,并选择Run AS (运行为)> Mobile Application(移动应用程序)。
- 2.选择On desktop(在桌面上)并选择一个要模拟的设备。 例如Google Nexus One(参见图3)。
图3. 选择一个要模拟的设备。
- 3.点击Run(运行)并测试应用程序。 该应用程序应该看起来像是这样(参见图4):
图4. 应用程序应该看起来像是这样。
第二部分:使用移动项目渲染器
在本章节中,您将会定义一个移动项目渲染器,用于显示员工列表。
步骤
- 1.打开EmployeeDirectoryHome.mxml,然后为员工列表定义一个内联式的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 >
- 运行和测试应用程序。 该应用程序应该看起来像是这样(参见图5):
图5. 该应用程序应该看起来像是这样。
第三部分:在视图之间浏览
在本章节中,您将会创建一个EmployeeDetails视图,该视图会显示列表中所选员工的详细信息。 您将学习如何在视图间浏览和传递信息。
第一步:创建EmployeeDetails视图
- 1.右键单击EmployeeDirectory项目中的views文件夹,然后选择New(新建) > MXML Component(MXML组件)。 指定组件名称为EmployeeDetails,然后点击Finish(完成)(参见图6)。
图6. 指定组件名称为EmployeeDetails。
- 2.请按照下列代码实现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" > <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 >
第二步:打开详细信息视图
- 1.打开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 >
第三步:运行应用程序
- 1.在列表中选择一个员工。 所选员工的员工详细信息视图应该会显示出来(参见图7)。
图7. 所选员工的员工详细信息视图会显示出来。
第四部分:创建一个操作栏
在本章节中,您将会为这个Employee Directory应用程序创建一个操作栏(action bar):
- 1.您将会为应用程序的所有视图提供一个Home按钮,用户可以点击该按钮返回到应用程序的第一个视图。
- 2.您还会为EmployeeDirectoryHome视图的操作栏提供用于搜索员工信息的搜索控件。
第一步:创建一个Home按钮
- 1.打开EmployeeDirectory.mxml,然后定义以下的导航栏内容(在结束标签之前):
<s :navigationContent > <s :Button icon= "@Embed('assets/home.png')" click= "navigator.popToFirstView()" /> </s :navigationContent >
- 2.运行并测试应用程序。 请注意,由于导航控件是在应用程序级别定义的,因此它会被应用程序的所有视图共享(参见图8)。
图8. 应用程序的所有视图共享导航控件。
第二步:创建一个搜索栏
- 1.打开EmployeeDirectoryHome.mxml。
- 2.添加下面的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 >
经过这样初步实现之后,无论您在搜索框中输入什么内容,点击search按钮都将会返回所有员工信息。 您将会在第六部分中实现一个能够正常运行的搜索功能。
- 3.由于我们现在是在用户点击Search按钮时发送数据请求的,因此请删除在视图中定义的creationComplete处理器代码。
- 4.运行并测试应用程序。
请注意,EmployeeDetails和EmployeeDirectoryHome视图都继承了在 EmployeeDirectory.mxml中定义的Home按钮。 虽然总的来说让应用程序的所有视图共享一个Home按钮是一个好主意,但是没必要(而且可能会令人迷惑)让应用程序的Home视图也包含一个Home按钮 (参见图9)。
图9. EmployeeDetails和EmployeeDirectoryHome视图都继承了EmployeeDirectory.mxml中定义的Home按钮。
第三步:删除EmployeeDirectoryHome视图中的Home按钮
- 1.打开EmployeeDirectoryHome.mxml,然后在标签前面添加一个空的navigatonContent标签:
<s:navigationContent/>
- 2.运行并测试应用程序(参见图10)。
图10. 删除Home按钮
请注意,当您打开一个员工的详细信息视图然后又使用您的设备的返回按钮(或者应用程序的Home按钮)返回到员工列表时,该列表是空的。 这是因为当另一个视图被激活时,前一个活动视图会被自动销毁。 当您点击返回按钮时,前一个视图实际上被重新初始化了。
第四步:保留搜索结果
虽然一个视图会在它变为非活动状态时被销毁,但是它的“data”属性会被保留并在该视图重新初始化的时候被重新分配。
要利用data属性来保留搜索结果,您需要进行以下操作:
- 1.在您将HTTP服务调用的lastResult属性指定为视图的data属性的HTTPService对象中添加一个结果事件处理器。
<s :HTTPService id= "srv" url= "assets/employees.xml" result= "data=srv.lastResult.list.employee" />
- 2.将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 >
- 3.运行并测试应用程序。
第五部分:集成设备功能
在本章节中,您可以允许用户向应用程序中的员工打电话、发短信或发邮件。
第一步:显示一个操作列表
- 1.在EmployeeDetails.mxml中,在s:HGoup开始标签的前面添加一个代码块。
<fx :Script > <! [CDATA [ ] ] > </fx :Script >
- 2.在新的fx:Script代码块中,定义一个绑定的ArrayCollection对象来存放对于所选员工可以使用的操作列表:
[Bindable ] protected var actions :ArrayCollection;
注:为了编译此代码,请确保您已经导入了ArrayCollection类:
import mx.collections.ArrayCollection;
- 3.定义下面的嵌入式图标。 您将会在操作列表的itemRenderer中使用它们。
- 4.重写视图的“data”属性的setter,基于可获取到的数据使用员工对象的可用操作来填充操作列表。 例如,“SMS”操作应该仅在可以获取手机号的情况下提供给用户。
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 } ); } }
- 5.显示操作列表:在结束标签的下面,添加一个绑定到操作列表的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 >
- 6.运行并测试应用程序。
当您在列表中选择一个员工时,您应该可以看到对于该员工可以使用的操作列表(参见图11)。 这些操作目前还没有被实现。 您将会在下一步中实现它们。
图11. 该员工可以使用的操作列表。
第二步:触发动作
- 1.向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 >
- 2.按照下面的代码实现ist_changeHandler:
protected function list_changeHandler (event :IndexChangeEvent ) :void { var action : Object = list.selectedItem; switch (action. type ) { case "tel" : break; break; } }
注:为了编译此代码,请确保您已经导入了spark.events.IndexChangeEvent(不是mx.events.IndexChangedEvent):
import spark.events.IndexChangeEvent;
- 3.运行并测试应用程序。
第六部分:使用一个RemoteObject
在本章节中,您将会实现搜索功能。 您将会使用一个提供了findByName方法的RemoteObject替换HTTPService。 为了您的使用方便,RemoteObject是存在于云服务器中的,因此您不需要在您自己的基础架构中部署任何代码。
当然您也可以使用HTTPService来实现搜索功能。 我们换用RemoteObject的原因是为了体验不同的数据访问策略。
如果您对使用RemoteObject不感兴趣,您可以直接跳转到第七部分。
步骤
- 1.打开EmployeeDirectoryHome.mxml。 使用下面代码定义的RemoteObject替换HTTPService:
<s :RemoteObject id= "srv" destination= "employeeService" endpoint= "http://flex.org:8080/extras/messagebroker/amf" result= "data=srv.findByName.lastResult" />
- 2.修改搜索按钮的click处理器:使用RemoteObject的findByName方法来查找匹配用户输入的搜索关键字的员工。
<s :Button icon= "@Embed('assets/search.png')" click= "srv.findByName(key.text)" />
- 3.运行并测试应用程序:在搜索框中输入一些字符,然后点击搜索按钮来查看匹配的员工列表(参见图12)。
图12. 在搜索框中输入一些字符并点击搜索按钮查看匹配的员工列表。
第七部分:使用本地SQLite数据库
在本章节中,您将会改变应用程序的数据访问逻辑:您会使用您的设备中的SQLite数据库来访问数据,而不是使用一个RemoteObject(或一个HTTPService)。
步骤
- 1.从FlexAndroidWorkshop文件夹中复制model目录,然后将其粘贴到EmployeeDirectory项目的src目录下。
- 2.让我们来研究一下EmployeeDAO和Employee类的源代码:
- EmployeeDAO类提供了Data Access Object(数据访问对象)模式的一个基本的实现:它包含了创建、更新和删除员工的数据访问逻辑。如果数据库中不存在employee表,那么 EmployeeDAO还包含创建这个表以及使用样例数据填充这个表的一些逻辑。
- Employee是一个基本的值对象,该值对象还提供了一些根据需要加载员工的经理和直接下属的延迟加载逻辑。
- 3.在EmployeeDirectoryHome.mxml中,使用一个EmployeeDAO实例替换RemoteObject(或者HTTPService,如果您没有完成第六部分的话)。
<model:EmployeeDAO id="srv"/>
注:请确保model命名空间已经在该mxml文档顶部的View定义中进行了绑定。
-
<s :View xmlns :fx= "http://ns.adobe.com/mxml/2009"
-
xmlns :s= "library://ns.adobe.com/flex/spark"
-
title= "Home" xmlns :model= "model.*" >
- 4.相应地修改搜索按钮的click事件处理器。
-
<s :Button icon= "@Embed('assets/search.png')"
-
click= "data=srv.findByName(key.text)" />
请注意,在此情况下,我们可以直接指定findByName函数的返回值为data,因为EmployeeDAO使用了数据库访问API的同步版本。
- 5.运行并测试应用程序。
第八部分:浏览组织结构图
在本章节中,您将会向Employee Details(员工详细信息)视图添加“View manager”(查看经理)和“View direct reports” (查看直接下属)操作,以允许用户向上或向下浏览组织结构图。
第一步:创建DirectReports视图
- 1.在EmployeeDirectory项目中右键点击views文件夹,并选择New(新建) > MXML Component(MXML组件)。 指定组件名称为为DirectReports,然后点击Finish(完成)(参见图13)。
图13. 指定组件名称为DirectReports。
- 2.按照以下代码实现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 >
第二步:添加浏览组织结构图的操作
- 1.在EmployeeDetails.mxml中,添加两个可能的操作来设置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 } );
-
}
- 2.在List组件的change处理器中,添加两个case语句来触发相应的动作:
-
case "employee" :
-
navigator.pushView (EmployeeDetails, action.employee );
-
break;
-
case "reports" :
-
navigator.pushView (DirectReports, action.employee );
-
break;
第三步:运行应用程序
- 1.选择一个有经理的员工(参见图14)。
图14. 选择一个有经理的员工。
- 2.点击“View manager”操作(参见图15)。
图15. 点击"View manager"(查看经理)。
- 3.选择一个有直接下属的员工,然后点击“View direct reports”(查看直接下属)操作(参见图16)。
-