深入分析Flex[Bindable]及使用方法
在學習Flex的過程中,你可能會遇到Flex[Bindable]方面的問題,這里和大家分享一下,希望本文的介紹能讓你有所收獲。
深入分析Flex[Bindable]及使用方法
◆Flex[Bindable]大概又是Flex用得最多的元數據了。剛開始用用確實好簡單,效率真是沒的說。不過這幾天用著卻碰到了些問題,我自己搜集了些資料,想著有必要在blog里總結一下吧。
啥是元數據(metadata)
今天不曉得為什么livedoc.adobe.com這么慢,沒辦法,拿不到權威的解釋了。我就按自己的理解隨便解釋一下:首先要明白元數據不是語法的一部分,而是專門給編譯器用的,說白了是告訴編譯器做某些事情,學過java之類的應該知道。那Bindable來講,它的作用是告訴flex編譯器,給某些某些東西建立綁定關系,flex編譯器會在編譯過程中給AS(flex編譯器就是把mxml編譯成as,再編譯到swf,也可能直接編譯倒swf,我這里假設有as這么個環節)加一點事件發生和處理之類的代碼,由此綁定的關系便建立了,如果我們用純粹as3代碼來寫也是可以實現的,就是太太太麻煩。
舉個例子:給下面的public變量加上Flex[Bindable]
- Flex[Bindable]
- publicvarname:String="";
◆作為一個public變量,肯定既可以被賦值,也能賦值給別的變量。綁定的作用就是,當name改變的時候(被賦值了),可能通知其它被name影響(賦值給它們)的變量發生改變。這里的“可能”就需要編譯器來判斷,這就是為什么元數據是給編譯器用的原因了。在mxml里用{}的語法的地方就是綁定的對象,比如label={xxx.name},當name變化,label也跟著變化。這樣,我們只是很簡單的改變了name的值,由于有綁定,界面上的label也跟著自動變化了,爽吧。
能用在哪里
三個地方:類,變量,getter/setter。是不是public沒有關系,private的就只能給自家用唄。用在Class上就是簡單的給所有的public屬性(包括變量,getter/setter,普通方法)加上Flex[Bindable],可是一般的方法不能用Flex[Bindable]呀,于是一般就能看到flex給了個warning,直接無視:)。變量嘛就是上面講的,很簡單略掉。
用在只讀,只寫屬性(getter/setter)上面
終于講到關鍵地方了,因為getter和setter很像方法,用起來會有點不同。看看這個例子:
- Flex[Bindable]
- privatevarcontent:Array=newArray();
- Flex[Bindable]
- publicfunctionset_content(ct:String):void
- {
- content=ct.split(SEP);
- }
- Flex[Bindable]
- publicfunctionget_wholeText():String
- {
- if(content.length==0)
- {
- return"";
- }
- else
- {
- var_w:String="";
- for(vari:int=0;i<content.length;i++)
- {
- _w+=content[i]+"\r\n";
- }
- return_w;
- }
- }
◆原來的設想是content綁定_wholeText,可它是不工作的。為什么?_wholeText太復雜了,被編譯器排除在“可能”之外,編譯器認為沒有綁定關系,如果只是簡單的returncontent,倒是可以的。我這里搜到了一些比較權威的解釋。來自http://www.rubenswieringa.com/blog/binding-read-only-accessors-in-flex找到ElyGreenfield講的。
- Nowkeepinmindthatthere’snowayforthecompilertoactuallytellifthevalueofapropertygetfunctionwouldbedifferentifcalled,
- shortofdoinganextensivecodeflowanalysisofthegetfunction,
- identifyingalltheinputsthatmightbeaffectingthevalueofthegetfunction
- (i.e.,memberfields,statics,globalsthatareusedinthegetfunctionandinanymethods,globalfunctions,closures,etc)itmightcall,
- andsettingupwatchersoneveryoneofthosetotriggerthebindingwhenanyofthemchange.
- That’sprohibitivelydifficult,andexpensivetodo.Sothecompilerdoesn’ttry.
- InsteadwhenyouputFlex[Bindable]onaget/setproperty,
- thecompilermakesitbindablewithalittlecreativerewritingthatallowstheframeworktowatchthegetfunction,
- anddispatchachangeeventwhenthegetfunctionistriggered.Thismeansthatautomaticbindablepropertiesdon’
- tworkwhenthegetfunctioniscomputedfrommultiplevalues,
- orwhenyouchangeitsvaluebysettingabackingfield,ratherthanusingthesetfunction.
- It_also_meansthatifyouhavenosetfunction,
- wecanprettymuchguaranteethatthere’snowayautomaticallybindablegetpropertieswillbetriggered.areadonlypropeertyis,
- tothecompiler,completelyopaque…atthemoment,ithasnoideawherethatvalueiscomingfrom,
- andhencewillneverbeableto‘automatically’triggerthebinding.
說白了就是為了降低復雜度和提高效率,復雜情況的getter會被忽略。如何解決?可以手動建立綁定,即[Bindable("eventName")]。把代碼改成這樣:
- Flex[Bindable]
- privatevarcontent:Array=newArray();
- Flex[Bindable]
- publicfunctionset_content(ct:String):void
- {
- content=ct.split(SEP);
- this.dispatchEvent(newEvent("_contectChanged"));
- }
- [Bindable("_contectChanged")]
- publicfunctionget_wholeText():String
- {
- if(content.length==0)
- {
- return"";
- }
- else
- {
- var_w:String="";
- for(vari:int=0;i<content.length;i++)
- {
- _w+=content[i]+"\r\n";
- }
- return_w;
- }
- }
這樣就避免了編譯器去自動識別。自己加上綁定關系,當_content被賦值,發出_contentChanged事件,通知所有被綁定的getter方法執行一遍。這也說明了,綁定不過是事件游戲而已,flex為用戶隱藏了很多底層算法。
【編輯推薦】