HFCD: 快速Flex編譯器

July 2nd, 2010

HFCD( Hell Fire Compiler Daemon ) 是由 Clement Wong(http://stopcoding.wordpress.com/)開發的,他原本是Flex SDK team的一員負責compiler的種種(難怪XD)。
如果你也常維護比較大的Flex專案,我想會很需要節省每次重新compile的時間的,實際測試過之後,比官方編譯器大約快了一倍(個人感覺啦)。安裝的方法如下:

  1. 到:
    http://bytecode-workshop.com/#section=downloads
  2. 下載: 3.5/4.0 的安裝檔
  3. 安裝, 設定eclipse home(例: C:\Program Files\Adobe\Adobe Flash Builder 4 Plug-in\eclipse-host-distro), sdk home, workspace dir 要正確
  4. 啟動HFCD daemon
  5. 打開FlashBuilder
  6. 到你的專案properties, 變更 compiler 為 HFCD 3.5/4.0
  7. 完成

找不到ant control lib時

May 30th, 2010

要到這裡找:

http://ant-contrib.sourceforge.net/

通常把jar放在

%ANT_HOME/lib

底下。當然也可以分開放啦…
但eclipse用的env.ANT_HOME不是ANT_HOME喔,可能是c:\eclipse\plugin\….,要特別注意。

MVP: Supervising Controller, Passive View

May 18th, 2010

原文:

由MVP(model-view-presenter)衍生出來的兩個design pattern,共同的優點是:

  • 讓Controller(Presenter) classes 更容易test(enhance testablilty)
  • 將view的操作邏輯、事件處理等等分離出來

兩者差異:
Passive View 完全地去除對Model的依賴,”更新view的資料顯示”的工作全部由presenter去執行,因此也不需要依賴諸如DataBinding等observer pattern的功能;相對地,Supervising Controller 可以將”更新view的資料顯示”交給DataBinding去執行。

見圖:(ref: http://martinfowler.com/ )
Supervising Presenter:
supervising presenter class diagram

Passive View:
Passive view class diagram

NetBeans + Scala + Scala IDE

April 28th, 2010

NetBeans+Scala+Scala Plugin安裝方法:

下載:

NetBeans:
http://netbeans.org/downloads/index.html

Scala 2.8 RC1 (不能用2.77) :
http://www.scala-lang.org/downloads/distrib/files/scala-2.8.0.RC1.zip

Scala IDE Plugin:(ref:http://blogtrader.net/)
http://sourceforge.net/projects/erlybird/files/nb-scala/6.8v1.1.0rc2/

安裝:

  • 裝 scala : 把scala.zip解開到你要的目錄, 設定環境變數: SCALA_HOME =[你的scala目錄] 以及 PATH=[你的scala目錄\bin]。設定好之後到command line之下打: scala 應該要看到scala的基本資訊。操作畫面如下:

  • 裝 netBeans
  • 裝 Scala IDE Plugin: 下載好之後,把下載的zip檔解壓縮到某處。
    打開裝好的NetBeans,進入”Tools” ->”Plugins”, 選”Downloaded” tab,選”Add Plugins…,選剛剛你解壓縮的地方,把所有的*.nbm檔案都選起來,安裝後重新啟動NetBeans即可。

建立測試用 Scala Project:


執行經典Hello World:

如果沒意外應該會看到Output裡面有”Hello World”。

Google Chrome 與 Adobe Flash Player 攜手合作

April 2nd, 2010

原文連結:
Chrome Blog

Adobe Flash Blog

簡單來說,Chrome目前會做三件事:

  • Chrome 會自動下載最新版本Flash Player ,不用分開安裝
  • Chrome 會自動更新最新版本Flash Player ,不用自己手動更新
  • Chrome 會擴大Flash Player 對瀏覽器的控制範圍

Google、Adobe、Mozilla 正再製作下一帶的瀏覽器外掛API,使Flash Player之間的互動更加密切,不用ExternalAPI去控制Javascript和HTML DOM 了。

update:
下載Google chrome dev 版本後,要記得加上啟動參數:

-enable-internal-flash

然後啟動chrome會看到:

這樣應該就行了 :)

利用GroupingCollection幫你分組

March 26th, 2010

有些時候我們有一堆資料物件, 需要根據物件的某個屬性值作分類, 最直接的方法就是跑個迴圈,如:

var hash:Object = {};
for each( var obj:Object in objectList )
{
//檢查obj的屬性值
if( obj.name in hash )
hash[obj.name].addItem( obj );
else
hash[obj.name] = new ArrayCollcetion([obj]);
}

//結果就是根據 obj.name 值分類好的hashmap

但我們可以利用Flex的GroupingCollection幫我們作這個工作, 而且過程封裝的更好:

var groupingCollection:GroupingCollection();
var gping:Grouping = new Grouping();
var field:GroupingField = new GroupingField("你要分群組的屬性名稱");
//給予要群組的屬性, 可有多個GroupingField,
//會依序群組, 非常類似SQL::GROUP BY
gping.fields = [ field ];

groupingCollection.grouping = gping; //設定Grouping
groupingCollection.source = 原始資料 (通常是ArrayCollection);
groupingCollection.refresh(); //叫GroupingCollection開始工作

//重要的來了, 呼叫getRoot()取得GroupingCollection幫我們分群好的資料:
//結果通常是一個新的ArrayCollection, 裡面有多個Object ,
//每個 Object 有一個children屬性, 包了分組好的物件(原物件)
//Object本身有個預設的GroupLabel屬性,是根據你的資料內容的群組名稱
var result:Object = groupingCollection.getRoot();

預設的GroupLabel屬性名可以透過: Grouping#label 改成你想要的屬性名稱。
或許你會覺得這哪裡好,比一開始的還要複雜很多,其實他的威力不只是分群,還可以幫你分群作加總、求最大/最小值/平均值的功能呢,利用 SummaryRow 就可以輕鬆作到喔!

var summaryRow:SummaryRow = new SummaryRow();
var smryField:SummaryField = new SummaryField("price","SUM"); //price ==> 要處理的屬性名稱
summaryRow.fields = [smryField];
var groupField:GroupingField = new GroupingField( "name" );
groupField.summaries = [ summarRow ] ;
...參考上方

上述結果是一個根據物件的”name”屬性分組,並且根據物件的”price”屬性作加總的GroupingCollection。同樣地利用getRoot();取得結果,可以看到新建立出來的Object#children除了有分群好的物件之外,還多出了SummaryObject,裡面就是幫我們算好的值。

補充:

自訂群組結點的標籤產生方式:

GroupingField#groupingFunction :
自訂group object#label的方法,在label不是單單靠某屬性值就能解決的情況,特別好用。 ex: 想作出一個group#lable = vo.name + vo.lastName + vo.id
signature:

groupingFunction(item:Object, field:GroupField):String

特別注意的: 當你覆寫了這個方法同時,記得也要覆寫 GroupingField#compareFunction,因為GroupingCollection建立GroupingCollectionView的時候會先對原始內容(來源ListCollectionView)排序,再產生Grouping(這樣效能比較好)。因此假設你的compareFunction並沒有寫好,那麼你會常常看到同一個群組結點標籤出現在不同的群組結點上。如果你不想用compareFunction,那麼,至少GroupingField#name的值對排序要有意義。

自訂群組結點物件內容:

GroupingField#groupingFunction :

產生group object的方法,當你不想要用預設的groupobject + label的方法,可用此方法自訂一Grouping Object的結構。
signature: myGroupObjectFunction(label:String):Object

Embeded font

December 19th, 2009

常用的Embeded font 寫法,從Adobe手冊抄來的:
重點是: 用同一個Font Family Name 但是Embed不同的Font Face, 這樣可處理大部分的字型問題,不然,常常會有字形粗體時跑回Arial, Tahoma 的情況。

@font-face {
        src:url("../assets/MyriadWebPro.ttf");
        fontFamily: myFont;
        advancedAntiAliasing: true;
     }

     @font-face {
        /* Note the different filename for boldface. */
        src:url("../assets/MyriadWebPro-Bold.ttf");
        fontFamily: myFont; /* Notice that this is the same alias. */
        fontWeight: bold;
        advancedAntiAliasing: true;
     }

     @font-face {
        /* Note the different filename for italic face. */
        src:url("../assets/MyriadWebPro-Italic.ttf");
        fontFamily: myFont; /* Notice that this is the same alias. */
        fontStyle: italic;
        advancedAntiAliasing: true;
     }

see:
http://livedocs.adobe.com/flex/3/html/help.html?content=fonts_04.html#133099

[Embed(systemFont='Myriad Web Pro',
        fontStyle='italic',
        fontName='myItalicFont',
        mimeType='application/x-font',
        advancedAntiAliasing='true'
     )]
     private var font2:Class;

好用的Flash Builder 快速鍵( hotkey )

November 13th, 2009

這也是從Adobe TV的MAX2009 session 聽來的,完整版請到adobe.tv看。

  • Ctrl+3 : 顯示快速command列表, 可以type-and-search執行所有的eclipse command
  • Ctrl + I : 自動縮排的妙用: 由別的文字檔貼過來的文字,全選後按下此快速鍵會自動排列。文字游標(I-Beam)移到任何地方按下此快速鍵,自動移到應該要去的地方,省得你按一堆tab和space
  • Ctrl+Shift+T:是open type, 這個大家都知道,但是奧妙在type-search的地方,可以打camel case string 作為搜尋;甚至可以用wildcard search. 舉例來說,想打開AdvancedDataGrid, 不用打Adv…去找,可打ADG就好( AdvancedDataGrid )。用wildcard search: 打 *skin 會列出所有 XXXskin相關的classes
  • Code assist : Alt+. (預設) 可以重複按,會自動filter分類,本來是顯示所有的屬性,每一次會顯示各類別: property, style, event

用Google Analytics 分析Flex應用程式

November 10th, 2009

Google 真的太威了…

安裝說明:
http://code.google.com/apis/analytics/docs/tracking/flashTrackingSetupFlex.html#getTheLibrary
取得library:
http://code.google.com/p/gaforflash/

注意:
GA tracking 的結果,不是及時的!
測試不是能夠直接看到結果的,必須等待幾個小時再到Google Analytics網站看報告。

你也在寫Flex嗎? 那你可能要特別注意…

November 10th, 2009

本篇文章來自MAX2009的session:
How Not to code FLEX

演講者主要說明何謂壞程式碼(bad code),但也說壞程式碼不一定不好,只要你確定能盡快回來改正他。那何謂壞程式碼?

  • Container 元件的誤用:Container元件諸如Box, Canvas, Tile等等,他們的原本目的都是: 排列裡面的子元件。因此只要你不是拿來排版或甚至沒有給予它任何的子元件,就違背原本用意了。
    例子:

    <mx:TextInput/>
    <mx:VBox backgroundImage="blah.png" borderStyle="solid"/> <!-- 你看, 沒有小孩的容器元件-->
  • ListBase 元件的誤用: List, TileList, DataGrid 都是用來針對列表物件的選取、排序、renderer回收而生,因此,當你想要製作的元件並不需要這些功能,就不該採用List來處理。
  • local model binding: 避免直接將值給UI元件,盡量用local model binding來處理。(按:此方法還可避免元件初始化延遲所帶來的問題)
    ex:

    <mx:script>

      //這樣是不好的
      function test():void
      {
         myLabel.text = "hello";
      }

    </mx:script>
    <mx:Label id="myLabel"/>
    <mx:Script>
    //用local model binding.
    [Bindable]
    private var helloText:String = "hello";
    </mx:Script>
    <mx:Label id="myLabel" text="{helloText}"/>
  • 別把local view event 交由非常上層的元件處理。(按:這裡必須搭配cairngorm microframework 來解釋 )
    元件與元件之間的訊息傳遞,如果能在local就解決,便盡量不要拋到上層的command-frontcontroller 去處理然後又繞回來”原本的元件”。以後維護會很辛苦。
  • 不適當的容器元件使用方法:
    如果你發現你的容器元件裡面只有一個子元件(child),那可能有問題。
  • Two dots and you are out.
    兩個參照你就出局囉!

    如果你的程式碼需要進入非常多的子元件,那就有問題了。如下:

    var hey:String = myBox.thisBox.thatBox.rightLabel.text;

    這是一個本質上的問題,應該要封裝這些子元件,若其他元件需要存取裡面的值,應該要透過Event(帶資料出來) 來幫你。

  • 自以為的聰明寫法並不好。
    這種情況會發生在複雜的binding寫法,像是:

    <mx:Button id="btn" enabled="{ isCheck &amp;&amp; ( firstBtn.enabled &amp; !secondBtn.enabled) &amp;&amp; (thirdBtn.enabled|| feelGood) }"/>

    應該要用function 去處理這些binding 邏輯:

    <mx:Script>
    private function getEnabled( a:Boolea , b:Boolea , c:Boolean , d:Boolean , e:Boolean ):Boolean
    {
    //邏輯應該在這裡描述啦:
    return a && (b&&!c) &&(d||e);
    }
    </mx:Script>
    <mx:Button id="btn" enabled="{ getEnabled(isCheck,firstBtn.enabled,secondBtn.enabled,thirdBtn.enabled,feeGood) }"/>