RIAWAVE – 一個輕量化的Flex 2 應用程式開發手法(5)
*常見問題解答
⊿每個 view (form)一執行時做那些事?
通常我們會在每個form 的開頭tag內加上 creationComplete=”init()”,等於是這支class 的進入點(類似java 中的 Main),然後在 init()內跑 addListeners()將所有該偵聽的事件向 ModelLocator 註冊。
⊿那些變數是每個 form 都需要使用的?
一般來說 ModelLocator 與 DAO 是大部份 form 會用到的,因此通常我會在 form 的最前面宣告下面兩個變數:
public var model:ModelLocator = ModelLocator.getInstance();
private var daoContact:ContactProvider;
當然 dao 的物件就要依 form 的功能不同而改變,但 model 的部份幾乎是不會變的
⊿當一個form要與另一個form溝通時該如何做?
可透過 ModelLocator進行dispatchEvent() 與 addEventListener() 進行,這樣做的好處是任何需要偵聽這個事件的物件都可以自由的加入偵聽行列。
唯一要注意的是 addEventListener()要使用 weak reference才能確保不會發生 memory leak。
⊿如何在event內夾帶要傳送的資料?
可使用 Flex framework 內建的 DynamicEvent class, 這個 class 是 dynamic的,因此可在裏面加上任何的property,範例如下:
Var event:DyanmicEvent = new DynamicEvent(“MyEvent”);
Event.myData = [1,2,3];
Event.date = new Date();
ModelLocator.getInstance().dispatchEvent( event );
但使用 DynamicEvent 的缺點是沒有效率,因為class為動態而非 sealed,vm在執行時速度會較慢,同時開發時也不能享有 type checking 的好處,因此不建議使用。
另一個方法就是使用 CustomEvent class,請參考本範例中 event.CustomEvent class。在這個class中,我們定義了兩個prop,分別是 data 與 msg,其中 data 通常是用來存放要傳送的物件(array、xml或其它任何東西) 而 msg 則是附加的說明訊息,通常是純文字(string)
⊿view/form 應該要切割成多細才算適當?
這要看程式的功能與需求才能決定,也需要很多的經驗不斷重構才能有好結果。
但大原則是:合理 與 邏輯性。
合理是指功能相近或類似的ui就放在一個 form 內,例如電話簿為例,聯絡人列表與新增、刪除按鈕就應該畫分在同一個form內,但 edit 則不一定該屬於同一個 form。
邏輯性則是指form 的切割在將來是否能保有彈性,面對可能的重構(refactoring)與功能變動是否可在影響最小的情況下完成?form 與 form之間的相依性是否能降到最低?
初學者通常會對該切割出多細的form感到困擾,建議可多觀察 mac os x 的介面設計與佈局,尤其注意其版面內隱藏的區隔線或方格,那通常就是潛在的 form 人選。
⊿此approach 主要優點
-這是一個極度輕量化的開發手法,它沒有一定的規範與樣版,只是一群 design pattern與 best practice 的集合
-流程簡化同時層級也減少,加快開發速度
-概念簡單易學,只要掌握大方向即可快速上手
-class數量減少,將來編譯完成之 swf 體積也會變小
-彈性高,易維護
-適合中小型專案快速開發使用
⊿這個approach曾被用於開發多大的專案?
我們的team過去兩年來皆使用 riawave 進行專案開發,最大的案子大約有四十個form,總class約兩百多個,開發時間為半年,共三名工程師參與。
該專案為一飯店內部使用的電子看板系統,需同時俱備後台上稿系統與前台多媒體播放系統,其中後台系統部份需支援多國語系、role-based 認証與授權與複雜的播放條件設定。
這個專案的順利完成代表者 riawave 足以應付中型的企業級應用程式,並能在多人協同下共同開發,同時仍確保系統彈性與易除錯性。
⊿使用這個方法開發 Flex RIA 專案能確保成功嗎?
不,沒有辦法。
世界上沒有任何一種方法能神奇的確保開發過程一切順利,頂多只能籍由一個些經驗的累積與良好手法規範,協助工程師儘量少犯錯並在一開始就將事情做對。
同時,相同的開發手法在不同的人手裏,往往也會有不同的效果,這完全取決於工程師對整體系統規畫/設計的成熟度與經驗而定,因此不同的人用同一個方法看一個案子,可能就會得到不同的想法與手法,最終的結果也就完全看個人造化了。
⊿所以,riawave 真的沒有什麼缺點嗎?
當然不(但我們希望是)。
這也是我們公開此approach 的主要原因,我們希望籍由大量的同儕檢視,能協助共同發現可能存在的缺點,並希望能找出合宜的解決方式然後回饋給flex/flash社群。
因此,我們希望看過此份文件與範例的工程師們,能多多提供回饋意見,請不吝針對您發現的缺點與可改進之處提出建議,我們可共同討論並共商改進之道。
聯絡方式:jeremy@twmug.com
版權所有,請勿轉載或改寫本文任何部份,如需複製使用請取得書面同意授權
Riawave – pattern-based best practices for flex 2 development
All rights reserved, 2006 Richtechmedia.com


18 Comments Add your own
1. 初学者n&hellip | September 18th, 2006 at 12:32 am
所有事件都由ModelLocator发送,所有Form都监听ModelLocator,这样事件多了会不会乱了- -b,通常开发之前是否需要画个事件流程图?有没有必要?这种图怎么画,例子里没见到。。
2. jeremy&hellip | September 18th, 2006 at 1:13 am
其實是不會,在 Cairngorm 裏這種情況更嚴重,它才是真的做到”所有”事件都透過同一個 EventDispatcher 發送,但到目前為止也沒看到亂過。
至於要不要畫圖是見人見智,通常我是會書面寫下每個form 會廣播出去的事件,另外在 ModelLocator 裏有晟會有 public static const 來標示每個事件,因此重覆或亂掉的機率不大。
3. Rita&hellip | September 18th, 2006 at 5:15 pm
嗯…Cairngorm並沒有要求全部事件都由CairngormEventDispatcher發送,它不會阻止你把事件交由其他方式發送,會用CairngormEventDispatcher發送的大多是很廣域的事件,或是有跟View Binding的事件,其他比較小範圍的事件,其實還是可以用其他的EventDispatcher處理。
事件的名稱多用public static const來處理,不一定要放在ModelLocator,如果事件多的話,多分幾個也可以,加上良好的命名,事件的管理會比較輕易一點。
4. 初学者n&hellip | September 19th, 2006 at 2:31 pm
ContactProvider也可以用单例吧
5. jeremy&hellip | September 19th, 2006 at 2:36 pm
之前 dao 是用singleton,但後來為了 memory leakage 的考量,轉而用 ModelLocator 廣播,它就不需要是 singleton了。
6. 初学者n&hellip | September 19th, 2006 at 3:12 pm
真效率啊~
大大,能不能讲讲内存泄露是怎么回事,还有你好象有一笔带过要用addlistener要用弱引用,不用弱引用就会内存泄露?why 。。。
ps。。刚接触flex,怎么让flex所有元件的字体都为12px。。偶现在要挨个加css。。。。
再ps。 台湾香港那边用qq么?
7. jeremy&hellip | September 19th, 2006 at 5:16 pm
當 A 物件要偵聽 B物件的事件時,會這樣寫
B.addEventListener(“eventName”, funct)
這時就會在 B 物件裏保持一份 A 物件的 instance reference,即始將來 A 物件已經被移除了(例如從 Display List裏用 removeChild(A)移掉),它仍然會被保存在 B 物件裏,這樣會導致 GC 運作時無法真正清掉 A物件佔用的記憶體,這時 memory leak 就發生了。
—
如果覺得字型太小,可以在 Application mxml tag裏加上 fontSize=”14″ 這裏的設定會透過 CSS 一路繼承到下面每個 mxml component,不用一個個元件去設定。
—
我不清楚其它人有沒有用qq,不過我沒在用。msn, aim, yahoo 似乎才是主流。
8. 初学者n&hellip | September 19th, 2006 at 8:56 pm
也就是说没有用弱引用,就跟as2一样,只是会占用一点点内存而已,不会造成大规模的程序瘫痪吧。
感谢详细的讲解,这里成了聊天的地方了。。等偶加您msn以后有问题方便再请教 ^_^
9. 初学者n&hellip | September 21st, 2006 at 12:01 pm
既然你说要用弱引用,那是不是最好在ModelLocator里 override public function addEventListener(type tring, listener:Function, useCapture:Boolean=false, priority:int=0.0, useWeakReference:Boolean=false):void{
super.addEventListener(type, listener, useCapture, priority, true)
}
弱引用没有坏处吧
10. jeremy&hellip | September 21st, 2006 at 12:39 pm
好主意,weak reference 對大部份正常使用情況應該都是無害的。
11. 初学者n&hellip | September 26th, 2006 at 4:28 pm
你好,你的msn好象没有在线的时候哦。。。
请教下不同State之间应该怎么通信?
比如我的dao会通过ModelLocator广播ONLOGIN_OK事件
这时我有两个States,s1,s2分别包含Form1和Form2
此时我在s1
Form1要监听这个ONLOGIN_OK,控制转入s2,
Form2也要监听这个ONLOGIN_OK,控制连接另一个服务
问题就是ONLOGIN_OK事件发生时,Form2还没有creationComplete,这种情况怎么做哦。。。
12. 初学者n&hellip | September 26th, 2006 at 5:01 pm
也就是说,我想每次从s1跳到s2时候都触发一个方法如果这个方法是creationComplete函数的话,只第一次跳的时候会触发,跳回s1再跳回来就不触发了,所以我才想到让这个Form也监视ONLOGIN_OK事件….不知道我说明白没。。。。
13. Hiso&hellip | September 26th, 2006 at 9:24 pm
不同States 的切換基本上都是在同一mxml內,var 或function 的東西都直接引用好了,不需用到ModelLocator,一般把事件如click=”currentState=’login’”改成click=”jumps2()”
而function jumps2(){
currentState=”login”;
你想作的事();
}
若Form1,Form2是兩個自製的component,可以在Form2 creationComplete時去寫一個如init()
function init(){
model.addEventListener(“ONLOGIN_OK”,你想作的事);
你想作的事();
}
function 你想作的事(){
Alert.show(‘HIHI’);
}
這樣應該在第一次和以後每次進入Form2時都會run你要作的事.
14. Hiso&hellip | September 27th, 2006 at 12:24 am
改成這樣應該就不會因為沒有代入參數而錯誤
function 你想作的事(…rest){
Alert.show(‘HIHI’);
}
15. jeremy&hellip | September 27th, 2006 at 5:57 am
to 初學者n:
Hiso 已經很詳細回答你的問題,參考一下吧。
btw,我經常不在座位上,msn通常是給人留言用的,所以有問題可以先傳過來,我回來看到訊息就會回。
16. fjufirefox&hellip | April 10th, 2007 at 7:07 pm
請問 jeremy , riawave 要適用其他語言如 jruby….
是不是只要改 dao 這個項目啊?
17. jeremy&hellip | April 10th, 2007 at 10:58 pm
呃 jruby 不是語言啊
你應該是指 flex/apollo + ror ?
以我們目前使用的經驗來看,搭配 weborb 確實只要改 dao 這塊就好,但當用的越久需求越複雜時就會發現 weborb 有許多歡樂的地雷,為了要 work around 這些事就必需要連帶改很多其它地方,這時歡樂度就開始降低了。
所以結論是這檔事一言難盡,等這段瘋狂忙碌期結束後再慢慢說。
18. fjufirefox&hellip | April 11th, 2007 at 9:49 pm
謝謝 jeremy
Trackback this post | Subscribe to the comments via RSS Feed