跳到主要內容

Dictionary And Proxy

今天來介紹二個 AS3 新增的二個類別(AS2沒有這東西喔)
Dictionary
簡單來說跟 Object 和 Array 是做一樣的事。
是用來索引物件用的類別。
Array是用數字來當做 Key 值。
_array[0] = "字串1";
_array[1] = "字串2";

_array[0] = "字串3";
時, 本來的值就會被取代掉
trace(_array[0]) //得到 字串3

Object是使用String來當作 Key 值
_obj['key'] = "String1";
_obj['key2'] = "String2";
(或寫成_obj.key2 = "String2";)

_obj['key2'] = "String3";
本來的值也會被取
trace(_obj['key2']) //得到 String3

Dictionary
是把'物件', 當作索引值,
每個物件都是獨立單一的, 這樣就可以確保索引值是唯一的。
var _dic :Dictionary = new Dictionary();
var _mc:MovieClip = new MovieClip();
var _mc2:MovieClip = new MovieClip();
//建立二個MovieClip
_dic[_mc] = "Dictionary Value1";
_dic[_mc2] = "Dictionary Value2";
用for in 掃一下內容。
for (var d:* in _dic) {
trace(d, _dic[d])
}
// [object MovieClip] Dictionary Value1
// [object MovieClip] Dictionary Value2
就可以得到當初寫入的值了
, 記得, 不要時一定要delete掉, 否則物件的指派還在
就不會被記憶體回被器回收喔。
完整程式碼:

package  {  
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.utils.Dictionary;

public class DictionaryDemo extends Sprite {    
private var _obj :Object = { };
private var _dic :Dictionary = new Dictionary();
public function DictionaryDemo()  {   

//_obj[Key] = Value
//但 Object 的 Key 必需是字串
//所以有可能會發生 Key 值已經用掉的問題

var _mc:MovieClip = new MovieClip();
_obj[_mc] = "數值1";
//這樣寫就等於 _obj[_mc.toString()] = 值。

var _mc2:MovieClip = new MovieClip();
_obj[_mc2] = "數值2";

//使用 for in 來掃obj裡的變數
for (var a:String in _obj) {
trace(a, _obj[a]);
// [object MovieClip] 數值2     
}

_dic[_mc] = "Dictionary Value1";
_dic[_mc2] = "Dictionary Value2";
for (var d:* in _dic) {        
trace(d, _dic[d])  
// [object MovieClip] Dictionary Value1
// [object MovieClip] Dictionary Value2    
}
}  
} 
}

Proxy , 代理人
好比我們要載入一個xml
要先透過URLLoader載入
然後再用一個XML物件把載入後的結果存起來
有沒有辦法整合成一個呢, 這時 Proxy 就很好用了
理想
var _xxx:類別 = new 類別
_xxx.載入外部("xml");
_xxx.偵聽事件。
載入成功後。
直接用_xxx.xml裡的tag名稱, 直接就當成xml使用。
先準備一份要載入用的XML文件





 



 


撰寫XMLProxy.as類別,
因為 Flash 不充許多重繼成, 但可以透過 Interface 來做到類似的效果,
所以XMLProxy要先extneds Proxy類別, 同時實作IEventDispatcher
package {
import flash.utils.Proxy; 
import flash.events.Event; 
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.net.URLLoader;
import flash.net.URLRequest; 
import flash.utils.Proxy;
import flash.utils.flash_proxy; 
[Event(name = "complete", type = "flash.events.Event")]
//加入這組 tag , 是要給 FlashDevelop 或是 Flex 在編程式碼時能有事件提示。
dynamic public class XMLProxy extends Proxy implements IEventDispatcher {  
//extends Proxy 時, 一定要設定成 dunamic 類別
private var _eventDispatcher:EventDispatcher;  
private var _urlLoader  :URLLoader;
private var _xml   :XML;  
private var _isLoaded  :Boolean;

public function XMLProxy(){ 
_eventDispatcher = new EventDispatcher();   
_urlLoader = new URLLoader();
_urlLoader.addEventListener(Event.COMPLETE, xmlLoadedHandler);
}
private function xmlLoadedHandler(e:Event):void {
_xml = XML(_urlLoader.data); 
_isLoaded = true;
dispatchEvent(new Event(Event.COMPLETE, true, true));   
}
public function loadURL(url:String):void {
var urlRequest:URLRequest = new URLRequest(url);
_urlLoader.load(urlRequest);
}
flash_proxy override function getProperty(name:*):*{
var _name:String = String(name);
return _xml[_name];
}
//以下是因為 interface IEventDispatcher, 所以要實作一樣的 function 名稱。
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, weakRef:Boolean = false):void {
_eventDispatcher.addEventListener(type, listener, useCapture, priority, weakRef);
}
public function dispatchEvent(event:Event):Boolean {
return _eventDispatcher.dispatchEvent(event);
}
public function hasEventListener(type:String):Boolean {
return _eventDispatcher.hasEventListener(type);
}
public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {
_eventDispatcher.removeEventListener(type, listener, useCapture);
}
public function willTrigger(type:String):Boolean {
return _eventDispatcher.willTrigger(type)
}  

public function get isLoaded():Boolean { return _isLoaded; }
}
}


完後成, 測試吧。
package  {  
import flash.display.Sprite;
import flash.events.Event;

public class XMLProxyDemo extends Sprite{  


private var _xmlProxy:XMLProxy = new XMLProxy();
//建構 XMLProxy 類別
public function XMLProxyDemo()  {   
_xmlProxy.addEventListener(Event.COMPLETE , _xmlCompleteHandler);
//偵聽事件, 因為實作了 IEventDispatcher , 所以也可以發送和偵聽。
_xmlProxy.loadURL("xml_data.xml");
//載入 xml。
}  

private function _xmlCompleteHandler(e:Event):void {   
//載入完成後, 當去使用_xmlProxy物件的屬性時,
//如果是 _xmlProxy 本身有定義的屬性, 就會去讀該屬性。
/* 而在 XMLProxy 裡定義的這行, 就是當屬性沒有定義時, 就去找指定的物件裡的屬性
* 方法也是可以這樣做。
* flash_proxy override function getProperty(name:*):*{
var _name:String = String(name);
return _xml[_name];
}*/

trace(_xmlProxy.isLoaded);
//.isLoaded 是定義好的屬性。

trace(_xmlProxy.item[0].img.@src);
//.item不是 _xmlProxy 裡一開始就定義好的屬性, 透過 Proxy 代理, 去找指定物件的屬性
//就好像真的是_xmlProxy物件的屬性一樣。
trace(_xmlProxy.item[1].label);   

}
} 
}

留言

Unknown寫道…
>Dictionary
>是把'物件', 當作索引值,
>每個物件都是獨立單一的, 這樣就可以確保索引值是唯一的。

不太了解這句話,哈哈。
milkmidi寫道…
var _mc:MovieClip = new MovieClip();
使用Object
_obj[_mc] = "值"。
//這樣是把_mc.toString()當成Key
//所以有可能會被蓋掉

_dic[_mc] = "值"。
是把物件本身當作Key值,
Unknown寫道…
老師請問一下,dispaychEvent(new Event(客製事件,ture,ture),這個客製事件業可以始用Event的公用常數?

你在XMLProxy這個範例的xmlLoadedHandler()函式,發出的事件EVENT.COMPLETE

請問用公用常數,作客製事件有什麼要小心的
milkmidi寫道…
dispaychEvent(new Event(客製事件,ture,ture)
此時的客製事件,只是一個字串
但就有可能會發生打錯字的問題
比較好的做方法自己寫一個類別來extends Event
同時定義const 的 static 字串