除非你过去四年的编程生涯都是在五行山下度过的,否则必定对”富互联网应用”——或按潮人的叫法“RIA”——略有所闻。万一你真是如前所述的隐居型开发者,那我把重任交给 Google,请它帮你找出 RIA 的正式定义。我们暂且把它定义成,具有在设计上更注重更操作性和效率的用户界面,不同于传统 Web 应用那种“输入地址,等待网络传输一个 Web 页面,填写表格,点击按钮,等待网络传输另一个 Web 页面”的交互循环。AJAX 是一种 RIA,Silverlight 也是,但比它们出现早得多的,是 Adobe 的 Flash。
因为新鲜感,对 RIA 的关注重心,大都集中在 AJAX 和老朋友 JavaScript 等工具。但是过去三年里,Apple 迅速且戏剧化崛起,并在移动市场占有主导地位,对此产生了极大挑战。以最新的浏览器技术和宽带连接为前提来建立 Web 应用是不够的,因为连美国政府自己都做不到这两点。实际上,即使有最新的浏览器技术和最快的连接,只要开发人员打算用超越基本 HTML 的技术来开发 Web 应用,就会突然发现自己掉进了一个泥潭,互相冲突的浏览器实现、网络延迟、几十种 JavaScript 库、错估的用户预期,劈头盖脸而来。
起源... 个人选择
作为一个职业生涯中大部分时间都在关注后端的开发者,我从来都不太关心前端开发者使用的工具和技术。实际上我曾经把前端贬得一文不值,说那一头的大部分开发”除了看看像素变颜色就没有什么了”。这话比较难听,我承认,但你也应该承认,除开最近几年,传统应用的 UI 设计一向不是业内的时尚话题:放个表单,用户填两下子,然后提交给服务器,实质工作都是我们后端人员做的。所谓实质工作包括:验证所有的输入(免得万一用户真的是一名黑客,企图用 Telnet 伪装浏览器来跳过所有”完美的”JavaScript 验证逻辑);调用一些数据库和 Web 服务,说不定还是并行的;纠合一些模板技术或视图生成技术,准备好将要返回的各种 HTML、CSS 和 JavaScript 片段,组装起来;最后传输回去给浏览器渲染和显示。
多美好的时光。
不过最近有几件事情发生,迫使我重新认清 UI 行业的现状:
- 移动设备市场——iPhone、Android 还有 Windows Phone——火热到如果忽视它们就意味着从软件开发行业中退休。虽然我挺想提前退休的,不过短时间内经济上不可行,还有两个小孩要上大学呢。
- 说到孩子,我的大儿子非常热衷于成为一名游戏开发者,对父子携手完成一两个游戏构想也很有兴趣。当然,对于我们这些做“大事”、搞“企业”开发的人,游戏一般不是我们关心的主题……但是除了想多花点时间跟我儿子在一起,把应用"游戏化"的概念在网络经营和市场营销的圈子里正迅速走红,因此是值得多探讨一些。
- 说到游戏,游戏有许多有意思的情况:与传统基于表单的应用相比,它们有各种各样的沟通和展示需求。当然游戏不是个例——如果能加快响应速度,甚或实现离线使用,那么很多商业应用也会受益。不管我们多么希望可以假定每个用户有永久在线的宽带连接,严峻的现实是飞机上的互联网连接十分罕见,宾馆的 ISP 经常无缘无故消失,会议现场的无线连接太难以捉摸。事实上,公平地说,虽然我们在各种场合见到的网络连接多了,可是优质的的连接更难找了。 这种状况严重损害了传统浏览器客户端的效果。
- 最后,Adobe 找到了我,问我是否有兴趣从一个 Java 开发者的角度探讨 Flex,深入了解它并反馈结果。充分披露原则要求我申明他们付费让我写这批文章,但是基于个人诚实原则,其实我一直想找个借口来好好了解一下 Flex,所以他们的邀请乐得我“屁颠儿屁颠儿的”,可以这么说。
所以,我的计划就是照他们的要求,在 InfoQ 设一个专栏,以 Java 从业人员的眼光(而不是艺术家打扮画 Flash 故事板的 Web 设计师的眼光)来介绍 Flex,观察的角度不限于呆板的传统业务应用,还有各种不同的角度,包括游戏 / 游戏化,与已有的 Java 应用程序集成,以及作为移动设备客户端技术的适用性。
我们可以开始了吗?
入门
Flash 平台 (Flex 的基础) 几乎像浏览器一样普及,已经安装到全世界的浏览器中接近十年时间。它被当作一种透过浏览器向不知情大众强行送上可爱动画短片、视频剪辑和奇怪游戏的手段。多年以来,要想完成 HTML 规范规定之外的任何事情,这是除 Java Applet 以外的唯一方法,而 Java Applet 的问题一点也不少。显然,Flash 要求用户安装一个本地插件,但这是必要的代价,况且很多用户早就为了看跳舞仓鼠或者玩其他什么可爱游戏,已经下载安装过了。
不幸,很多开发者仍将 Flash 拒之千里,因为它最初是按照"创意"类用户的习惯设计的,采用了美工人员比较熟悉的概念,例如故事板、时间轴、动画效果等。完全没有什么表单栏、对象模型、核心验证逻辑组件之类的东西。这意味着,如果一位开发者想要利用这个平台,将不得不面对各种模样怪异的工具,陌生的术语,还有一帮子不灌可乐品咖啡的用户群。
除了外表的差异,Flash 平台其实和它的 Java 表亲很相似,都有一个基于字节码的执行引擎,都被移植到多种平台。(从很多方面来看,如果 Java“一次编写,处处运行”的口号没有那么多“如果”,真能在客户端成为现实,那差不多就应该是 Flash 插件的样子。)Flash 执行.SWF(读作"swiff") 文件而不是.class 或.jar 文件,这种文件格式也像.class 文件一样是公开的。而且几年前,Adobe 通过 Flex 开发包进一步开放了 Flash 平台,提供 Flex 的目的是让开发者不需要使用面向美工人员的 Flash 工具,也能轻松地创建 SWF。
因此,第一步是获取 SDK,这个可以在 Adobe 的网站找到。稍微观察下就可以发现,Flex 有几种下载,主要的不同点是授权协议模式 - 最大的"Adobe Flex SDK"包含若干基于 Adobe 自定开源协议的软件,有可能不被某些组织接受,所以 Adobe 提供了另一种下载"Open Source Flex SDK",基于 MPL 授权协议的。一般来说,除非你的组织有特殊严格要求,否则"Adobe Flex SDK"完全适合研究和原型开发用途,但是如果想投入商业产品应用,那么需要请律师先看一下授权协议。我们将用最新发布的 Flex 4.5 SDK 来进行讲解;如果你还没有准备好,花点时间完成下载吧。
下载回来的 SDK 是一个简单的 ZIP 文件,解压到你硬盘中任何方便的位置,最好放到离其他开发工具近的地方。在我的系统里,我喜欢把所有工具都放在"prg"目录下,所以 Flex SDK 在我的 Windows 电脑里就放在"C:\Prg\flex-4.5"的位置;请看图 1-1。在该目录下存放了一系列工具和文件,看过 JDK 目录的开发者会觉得它的目录结构很熟悉。"bin"目录存放着开发者心爱的各种工具(所以应该将其路径放进“PATH”环境变量),"samples"目录下有各种示例应用,还有其他目录就不一一说明了。
图 1-1
(提醒:看看图 1-1 中列出来的目录,文件"env.bat"是我自己创建的,用于快速设置 Flex 命令行开发环境。它是一个简单的批处理文件,里面设置 PATH 环境变量和终端窗口标题,在 Windows 下其内容如图 1-2。它假定同一个终端窗口下已经配置好 JDK 和相关工具。)
图 1-2
[blockquote]@SET ANT_HOME=C:\prg\apache-ant @SET JAVA_HOME=C:\prg\jdk_1.6.0 @SET FLEX_HOME=C:\prg\flex_sdk_4.5.0.20967 @PATH=%FLEX_HOME%\bin;%ANT_HOME%\bin;%JAVA_HOME%\bin;%PATH% @TITLE Flex 4.5 Prompt[/blockquote]
检验 Flex 是否已经安装好,最快最简单的办法是运行一下"bin"里面的一个工具——mxmlc,也就是我们马上就会认识的 Flex 编译器。所以,假设 C:\Prg\flex-4.5\bin 已经加到 PATH 变量,直接输入"mxmlc",看看有没有反应;如果一切都没问题,你就会看到传统编译器"我其实没有做任何事情"的响应,看图 1-3。
图 1-3
代码拿来(还有工具)!
开发者遇到新平台,写的第一个程序必然是"Hello World",不仅是向先驱 (Kernighan 和 Ritchie) 致敬,也因为它展示了我们可以用新平台写出的最简单的程序。对于某些平台,像最初的 C 编译器,只要三行文本和一次命令行调用就完成了一个有意义的可执行程序;当平台变得更复杂,构建的步骤也越来越复杂。(Java 开发者回想起“Hello,EJB!”所需的步骤,依然会不寒而栗。)Flex 还是比较简单的,虽然不至于只用一个文本文件就变出花来。
先搭脚手架
Flex 和 Flash 之间的关系非常像 Java 和 JVM -- Flex 是一个工具 (一整套 SDK,如果我们准确完整描述的话),用于生成字节码,然后和资源一起打包成适合在 Flash 平台上运行的.SWF 文件。按照 Flash 的执行方式,它需要某种执行引擎或者叫虚拟机来执行 SWF 文件。一般来说,当遇到 SWF 文件时,用户机器上已经安装好必要引擎 /VM,但也不一定;因此,要么让用户提前安装 Flash 平台,要么开发者在第一次运行的时候为用户即时安装平台。
从实际操作来说,前一段描述可以这么总结:对于 Web 应用程序,SWF 文件需要某种类型的 HTML 脚手架来帮助它“导入”Flash VM,很像 Java applet 加载 JVM 的情况。以前用 applet 的时候,要告诉浏览器"这儿有一个 applet",然后说明 JAR 文件的位置,最后启动正确的类。Flash 的所用的 HTML 脚手架与此类似,见代码段 2-1,它告诉浏览器"这儿有一个 Flash",然后指明要加载的 SWF 以及相关的具体环境。
代码段 2-1
<html> <body> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=4,0,0,0" width="1024" height="768"> <param name="movie" value="MyFirstFlex4App.swf" /> <embed src="MyFirstFlex4App.swf" width="1024" height="768" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" /> </object> </body> </html>
我们暂时可以忽略例中的大部分 HTML 基本骨架——关键元素在中间部分即 <OBJECT> 标签下的 <EMBED> 子标签。显而易见,"src"属性指定当在页面被浏览器加载显示时,被执行的 SWF 文件名。<PARAM> 标签描述该 SWF 文件所在的 URL;因为我们是在本地文件系统操作,所以该属性与 <OBJECT> 中的"src"属性完全相同。"width"和"height"属性的作用是不言而喻的。所有这些在 Adobe 的网站上有详细的描述,想了解所有标签的用途和可能参数的读者,请看这个链接还有这个链接。(简单补充一下,<OBJECT> 是给IE3.0 看的,<EMBED> 是给Netscape Navigator2.0 看的。是的,Flash 有这么老。)
有心人可以在浏览器里打开这个页面,看看会得到什么结果。虽然没多大看头,但是当作一个快速测试,检查一下机器上是否已经安装好了 Flash 插件。虽然这检查有点多余,不过万一真的没装,现在是一个很好的下载时机。
64 位?别提了,我说!别提了!
一句话说明 Flash Player 和 64 位浏览器的关系:它俩合不来。具体来说,Flash 还不支持 64 位浏览器,所以尝试在 64 位浏览器中运行 Flash 一定会失败。Adobe 回应说,"用 32 位版的浏览器算了,反正大家都用",以及"将支持 64 位",请参考这里。
水印和代码
Flex 就像 HTML 一样,是一种双管齐下的工具。一方面 ,开发者用标记语言(Flex 用的标记语言是 XML)来描述程序中的各种按钮、控件……以此完成用户界面组件的布局工作。如果只是显示一句静态的“hello, world”文本,那么只用标记语言就能轻松完成。不过, Flex 还有另一面,你还可以用它编写代码来响应各种控件触发的事件,而这些才是在开发人员用来完成“实际工作”的手段。为了演示这一面,我们来做一个稍稍复杂一点的例子 :在页面上创建一个按钮,然后用一个事件处理器来响应按钮事件并弹出一个消息框显示“Hello world”字样。
Flex 编译器 mxmlc 的处理对象是带“MXML”扩展名、以文本格式存储的标记语言脚本,所以请打开你信赖的文本编辑器,创建一个“MyFirstFlex4App.mxml”文件。(做好用一个能够理解 XML 语法的编译器,以避免类似忘记结束标记等明显的 XML 错误。)输入如代码段 2-2 所示的标记语言脚本。这只是一个入门例子,不要求理解其中的细节,只是让你体会一下语言和环境的总体感觉,顺便检查一下工具和运行时是否配置无误。
代码段 2-2
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768"> <s:Button x="17" y="14" label="Button" id="btnSayHello" /> </s:Application>
MXML 文件本身就是一种合乎规格的 XML 文件,所以里面的 XML 命名空间跟一般的 XML 命名空间并无不同,即限定不同的标记名称的语法作用域。可以把这些命名空间当作 Java 包的角色来看待。代码中声明的一长串命名空间前缀,实际我们只用到其中两个,fx:(下一个例子会用到)和 s:。多数 Flex 程序都喜欢把这一串命名空间写全,因为声明额外的命名空间不会对最后生成的程序有任何影响(就像导入未使用的 Java 包),所以可以算作一种好习惯,至少目前如此。
其余的标记比较简单明了:"s:Application"标签说明这是一个应用程序,它包含一个子控件"s:Button"。只要曾经编写过 HTML 表单,就不会对这几个标签的属性感到陌生,这是故意设计的。我们还没有说明按钮被点击时会做什么,但本着“早发布,常发布”的精神,我们先运行一下看看 。
在我的机子上怎么运行不了!
如果什么都没显示,或者出于某种原因,您的浏览器开始从 Adobe 下载软件,请勿慌张;先前搭建的 HTML 脚手架正在替用户忙碌,从 Adobe 网站上下载最新的 Flash 播放器。这一迹象表明你的机器还没有安装 Flash 播放器,等待几分钟,点击几个“你确定吗?”对话框,Flash 就应该准备好了。
还有问题的话,请访问 <<Adobe 的网址 >> 以验证 Flash 是否已经正确安装。如果还失败,你可能需要联系您的系统管理员去排除故障,这超出了本文所讲的范围。
构建
构建 Flex 应用程序必不可少的步骤是用 mxmlc 工具将 MXML 文件编译成 SWF 文件。假设 mxmlc 已经存在路径中,且.mxml 文件在同一目录,执行“mxmlc MyFirstFlex4App.mxml”,命令行编译器万年不变的工作过程就开始了 :它会回馈说明当前执行到的步骤,如果代码正确无误,执行完毕的时候目录下就会多出来一个新生成的.swf 文件。如果我们再次在浏览器中打开先前的 HTML 脚手架文件,等 Flash 插件加载完毕,就可以看到如图 2-3 的内容。现在的页面内容仍然没什么看头,因为当用户(你、我、或者刚好经过的大姨妈 Sally)点击按钮时没有任何反应。
图 2-3
代码
大姨妈 Sally 来早了——不管她怎么点击按钮都没有任何反应,Sally 很失望。修正这个问题,只要给按钮的"onClick"事件定义一个事件处理器就可以了,跟编写 HTML 表单是一样的。这是为了贴近 Web 开发而故意仿造了 HTML 的设计,用来编事件处理程序的语言也非常像 JavaScript,名为 ActionScript,熟悉它的开发者常简称为 AS。
对于简单的示例,直接把 AS 写在标记文件中比较简单,所以请打开刚才的.mxml 文件,然后把代码段 2-4 插入其中。有两个地方做了修改:"<fx:Script>"子标签下定义了事件处理函数,按钮的"click"属性声明了用户点击时将要执行的函数。如果您不熟悉"CDATA"标签,我稍作解释:它是一个特殊的 XML 标记,用来告诉 XML 解析器停止将"<"等标签分隔符当作标签分隔符来处理;不然在标记文件中写代码会非常麻烦,尤其是当有比较和布尔操作符 ("<"和"&") 的时候,因为需要对它们进行 XML 转义编码。(对不起,各位,但是"if (1 < 5)"和"if (x &&| y)"真的不太易读。)
代码段 2-4:
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768"> <fx:Script> <![CDATA[ import mx.controls.Alert; protected function btnSayHello_clickHandler(event:MouseEvent):void { Alert.show("Hello World"); } ]]> </fx:Script> <s:Button x="17" y="14" label="Button" id="btnSayHello" click="btnSayHello_clickHandler(event)"/> </s:Application>
有经验的 JavaScript 用户会很快注意到 JavaScript 和 ActionScript 的一些不同之处;Adobe 选择脱离传统的 JavaScript,尝试解决对 JavaScript 语言的一些常见批评。例如,ActionScript 比 JavaScript 有更严格的类型,所以 AS 的声明语句要求有"类型描述符",帮助编译器确认没有用错对象。ActionScript 在使用一个包 (库) 之前,先要进行引用,所以例中脚本块的开头有一行"import"语句。
函数的命名就像 JavaScript 一样没有什么规定,只是按照惯例写成"control_handler"的格式,如果这不符合你的编码习惯,请随意更改。(只是之后不要抱怨。)
重新编译代码产生一个新的 SWF,现在可以响应按钮点击了,在浏览器中重新载入"hello.html"页面,点击按钮会产生图 2-5 的结果。编程前辈们,接受我们的 Hello World 致意吧!
图 2-5
重复的工作
只要是写过 5 分钟 Java 代码的开发者,都知道 Ant 构建工具的好处——让人类从事任何重复工作都是在等着出错而已,随之而去还有生产力和发展势头。(如果你从来没有浪费过时间在调试上,从来没有遇到过编译失败,那就请你从本系列的下一篇文章开始看吧。) 因为 Flex 是像 Java 一样的综合开发环境,显然应该有一个与 Ant 角色地位相当的工具,Adobe 做得更好:他们没有重复造轮子,而是让 Flex 提供一系列 Ant 任务插件,让 Java/Flex 开发者易于将 Flex 集成到他们构建脚本中。
(是的,这意味着你需要安装 Ant,无论作为 IDE 一部分还是直接从命名行运行都可以(请参考这里)。如果你居然没有安装Ant,请自动摘下Java 开发者的牌子,回去弄你的COBOL 吧,我们会装作什么都没有看到。如果喜欢用Maven,那就要靠自己了——Adobe 没有提供现成的支持。尽管你可以找到一些教程说明如何把Flex SDK 安装到Maven 仓库,但老实说,如果你使用Maven……叫救命罢。马上。)
计划
我们有两个源文件,MyFirstFlex4App.mxml 是“真正的”Flex 布局和代码,还有一个 hello.html 是 HTML 脚手架,用来显示编译好的 Flash 应用程序。通常情况下,Java 惯例建议把所有代码文件放到项目根目录下的"src"目录,如果你还没有这么做,创建这个子目录然后把文件都放到这里吧。为了确保新的配置仍然有效,作为测试,再次启动 mxmlc,从"src"目录构建.SWF 文件,生成的输出文件再存放回该目录,请输入以下命令:"mxmlc src/MyFirstFlex4App.mxml "。当然,传统惯例是把生成的文件放到另一个目录(最起码使清理各种生成物更容易),mxmlc 同样支持此惯例,加上“output”命令行参数就可以了:" mxmlc src/MyFirstFlex4App.mxml -output dist/MyFirstFlex4App.swf"。
如果一切正常,我们就把上面的命令行转化成一个 Ant 构建文件。虽然用 Flex 提供的几个构建任务来编写可以使这个文件更简单,但我们还是循序渐进吧。直接用 <exec> 任务来编写,得到如代码段 3-1 的 Ant 文件,。
代码段 3-1:
<project name="MyFirstFlex4App" basedir="." default="compile"> <target name="init"> <mkdir dir="build" /> <mkdir dir="dist" /> </target> <target name="compile" depends="init"> <exec executable="mxmlc"> <arg value="src/MyFirstFlex4App.mxml" /> <arg value="-output" /> <arg value="dist/MyFirstFlex4App.swf" /> </exec> </target> <target name="clean"> <delete dir="build" /> <delete dir="dist" /> </target> </project>
Flex 任务
当然,使用 <exec> 标签最大的缺点是,我们不得不给每个参数都安排一个 <arg> 标签,参数多的话实在令人乏味。另外,对于写出来的 Ant 任务是否正确,我们没有任何验证手段,所以换成 Adobe 提供的 Ant 任务还是有好处的。替换工作非常简单,添加一个 Ant<taskdef> 导入 Flex 任务,然后改由 Flex 提供的任务元素去执行编译。
这里有个小提醒:按照 Flex SDK 的"Ant" 目录下 README 文件的说明,Flex 提供的 Ant 任务要求把 Flex 工具放到 PATH 环境变量,才能正确执行。既然我们一直以来都在用命令行构建,这应该不是一个问题;但如果之后用 Ant 构建出了问题,请检查这项设置。
切换到使用 <mxmlc> 任务,只要简单地把 <exec> 改成 <mxmlc>,然后把命令行参数套用为同名的属性,如代码段 3-2 所示。改成 Flex 任务之后代码变短了,因为现在编译参数被写成属性而不是 <arg> 子标签。
代码段 3-2:
<target name="compile" depends="init"> <mxmlc file="src/MyFirstFlex4App.mxml" output="build/MyFirstFlex4App.swf" /> </target>
搭建 Ant 脚手架
还差一个步骤才能让 <mxmlc> 正确执行,那就是告诉 Ant 在哪里可以找到 Flex 任务。这是 Ant<taskdef> 标签的工作,它需要引用"flexTasks.jar"文件,各种 Ant 任务就定义在这个文件里;还要引用"flexTasks.tasks" 文件,这个文件把标签名称 ("mxmlc") 映射到 JAR 文件中对应的 Java 类 ("flex.ant.MxmlcTask")。假设 Flex 安装在系统中 C:\Prg\flex4.5,<taskdef> 就应该写成像"<taskdef resource ="flexTasks.tasks" classpath="C:/Prg/flex4.5/ant/lib/flexTasks.jar" />"。当然,在你的机器上 Flex 不一定安装在同样位置(特别是如果您用 Mac 或 Linux 的话),这意味着,如果我们都在做同一个项目,马上就会有人感到沮丧:你的"/usr/local/flex-4.5"和我的"C:\Prg\flex-4.5"不可能妥协。如果在 Ant 脚本中直接嵌入 Flex SDK 的安装目录,那就只有"两个只能活一个"的办法才能解决问题。
Ant 用了属性文件来解决这个冲突:定义一个处于源代码控制之外的本地文本文件,名为“local.properties”,在文件中定义一个形如“name=value”的键值对:"FLEX_HOME=< 任意的安装位置 >"。然后把 taskdef 标签改写成"<taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar"/>",这样就皆大欢喜了。
接下来就可以用上 <mxmlc> 了,如代码段 3-3 所示。
代码段 3-3:
<project name="MyFirstFlex4App" basedir="." default="compile"> <property file="local.properties" /> <taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" /> <target name="init"> <mkdir dir="build" /> <mkdir dir="dist" /> </target> <target name="compile" depends="init"> <mxmlc file="src/MyFirstFlex4App.mxml" output="build/MyFirstFlex4App.swf" compiler.debug="true" /> </target> <target name="clean"> <delete dir="build" /> <delete dir="dist" /> </target> </project>
是的,这就是一段没意思的 Ant 代码,但现在打好基础将来会有回报。写好这段 Ant 脚本,以后所有的 Flex 项目都可以用它来做模板,就像当初 servlet 还新鲜的时候,我们给 Java/web-app 写的 Ant 脚本一样。
顺便一提,好奇的读者如果想了解编译器命令行参数的完整列表,请输入"mxmlc -help"即可,这个列表同时也是 <mxmlc> 标签属性的完整列表。Adobe 在 FlexSDK/ant 目录下的 README 文件中说明,编译器参数直接对应 Ant 任务的属性。因此,如果我们想启用命令行参数"- compiler.debug",就给 <mxmlc> 任务加上一个属性,"compiler.debug='true'"。
嗯,还行。就是有点小问题。
包装
问题当然就是,"hello.html"脚手架文件仍然存放在"src"目录下,为了得到一个完整的构建产物,它应该和.SWF 文件放到一起(反过来把.SWF 文件搬来和它放在一起也行,如果你乐意)。虽然我们可以直接用 <copy> 把文件从"src"搬到"dist"(生成到“build”目录下的.SWF 文件也照此办理,这样的目录结构是 Ant 惯例),但其实有一种更好的办法。
Flex 提供的几种 Ant 任务之中,有一个 <html-wrapper> 任务,顾名思义用于生成 HTML 脚手架文件。事实上,它会产生一个非常充实的脚手架文件,生成一段用来自动检测浏览器能力的 JavaScript 代码,等等。任务生成的 index.html 和 swfObject.js 两个文件,本文没有足够的篇幅详细解说,简而言之,这个脚手架比之前的"hello.html"要全面的多,因此是更好的选择。况且用 Ant 来生成这个脚手架一点都不费力气,如代码段 3-4 所示。
代码段 3-4:
<project name="MyFirstFlex4App" basedir="." default="compile"> <property file="local.properties" /> <taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" /> <target name="init"> <mkdir dir="build" /> <mkdir dir="dist" /> </target> <target name="compile" depends="init"> <mxmlc file="src/MyFirstFlex4App.mxml" output="build/MyFirstFlex4App.swf" compiler.debug="true" /> </target> <target name="dist" depends="compile"> <copy file="build/MyFirstFlex4App.swf" todir="dist" /> <html-wrapper title="Hello, Flex" height="640" width="480" swf="MyFirstFlex4App" output="dist" /> </target> <target name="clean"> <delete dir="build" /> <delete dir="dist" /> </target> </project>
总结
从入门到出师,还有很长的路要走:我们还要讨论两套 UI 组件、输入事件、远程通信、库,还要学一种完整的语言(ActionScript),学过这些基础之后,才真正进入到有意思的主题,例如动画、游戏(我个人的最爱)和移动设备(有争议的主题)等等。幸运地是,我有充足的时间时间慢慢写,Adobe 也有足够的预算来让我做这件事,所以这篇文章仅仅是“从 Java 开发者的角度学习 Flex 和 Flash”系列短文的第一篇。日后我们会逐一介绍 Flex 和 Flash 所提供的一切。
且听下回分解。
关于作者
Ted Neward是一名 Java 和.NET 开发者、顾问、作家,他发现自己对“让像素变变颜色”非常有兴趣。他居住在太平洋西北地区。
查看英文原文: Busy Java Developer’s Guide to Flex
感谢郭晓刚对本文的审校。
给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。
评论