面向Java開發人員的Flex開發指南

InfoQ - 黃玲豔發表於2015-02-05

除非你過去四年的程式設計生涯都是在五行山下度過的,否則必定對”富網際網路應用”——或按潮人的叫法“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所提供的一切。

相關文章