LoaderContext()建構函式
public function LoaderContext(checkPolicyFile:Boolean = false, applicationDomain:ApplicationDomain = null, securityDomain:SecurityDomain = null)
getDefinitionByName()全域函數
public function getDefinitionByName(name:String):Object
會傳回 name 參數所指定之類別的類別物件參照。
參數
name:String — 類別的名稱。
傳回值
Object — 會傳回 name 參數所指定之類別的類別物件參照
※ 本例著眼於 main.swf 載入外部 child.swf,透過LoaderContext類別物件予以設定,則child.swf 中所有的ActionScript 3定義,同時將被載入至main.swf所在的目前應用程式網域,並能被main.swf所取用。事實上,child.swf 中的ActionScript 3定義被合併至main.swf所在的目前應用程式網域,導致main.swf與child.swf 彼此擁有對方類別定義的能見度。
※ main.swf 載入child.swf 之後,可調用child.swf 的Child 類別裡的 weicom()方法。
而,child.swf 則可調用 Main 類別裡的 hello()方法,與 Ball 類別裡的 ballFunc()方法。

※ 這個測試,將main.swf及child.swf隔開在兩個不同的套件根目錄中,以避免相同套件內的存取造成誤判。




Main.as
package {
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.*;
import flash.events.EventDispatcher;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.system.ApplicationDomain;
import flash.display.MovieClip;
import flash.display.LoaderInfo;
import flash.utils.getDefinitionByName;
public class Main extends Sprite {
public static const LOADED:String = "loaded";
public var testVar:String;
private var ldr:Loader;
public function Main() {
this.testVar = "abc";
ldr = new Loader();
var req:URLRequest = new URLRequest("../external/Child.swf");
/*透過LoaderContext 指定 - 將外部Child.swf的公用類別定義載入到目前應用程式網域*/
/* ***藉由將載入的 SWF 檔置於相同的應用程式網域中,便可以直接存取其類別。*** */
var ldrContext:LoaderContext = new LoaderContext(false,ApplicationDomain.currentDomain);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
ldr.load(req,ldrContext);
}
private function completeHandler(event:Event=null):void {
trace("@Main / completeHandler() / event.target.content : " + event.target.content);
/*A法 : 使用ApplicationDomain.currentDomain.getDefinition()方法*/
/*取得Child的類別參照,調用其建構式*/
/*var getClass:Class = ApplicationDomain.currentDomain.getDefinition("Child") as Class;
trace("@Main / completeHandler / getClass : " + getClass);*/
/*B法 : 使用getDefinitionByName(name:String):Object*/
/*public function getDefinitionByName(name:String):Object*/
/*傳回 name 參數所指定之類別的類別物件參照*/
/*參數 name:String — 類別的名稱。*/
/*傳回值 Object — 會傳回 name 參數所指定之類別的類別物件參照。*/
/*使用getDefinitionByName()函數,取得Child的類別參照,代表子層類別可見度ok*/
var getClass:Class = getDefinitionByName("Child") as Class;
trace("@Main / completeHandler / getClass : " + getClass);
/*載入完成後, 建構一個Child類別實體, 指定給childObj - B法*/
var childObj:* = new getClass();
this.addChild(childObj);
/*載入完成後發送自訂事件*/
var loadedEvent:Event = new Event(LOADED);
childObj.dispatchEvent(loadedEvent);
trace("@Main / completeHandler() / this.dispatchEvent(loadedEvent) : " + this.dispatchEvent(loadedEvent));
/*調用childObj實體的welcome()方法, */
var message:String = childObj.welcome("Alice");
trace("***********************************");
trace("從Main調用Child的welcome()方法 - 以下這行");
trace(message);
trace("***********************************");
return;
}
public function hello():String{
var helloMessage:String = "@Main : Hello!!! Baby!!!";
return helloMessage;
}
}
}
Child.as
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.system.ApplicationDomain;
import flash.utils.getDefinitionByName;
public class Child extends Sprite {
public var getMainClass:Class;
public function Child() {
if(ApplicationDomain.currentDomain.hasDefinition("Main")){
/*A法 : 使用 ApplicationDomain.currentDomain.getDefinition()方法*/
/*this.getMainClass = ApplicationDomain.currentDomain.getDefinition("Main") as Class;*/
/*B法 : 使用getDefinitionByName(name:String):Object,取得Main的類別參照,代表父層類別可見度ok*/
this.getMainClass = getDefinitionByName("Main") as Class;
trace("@Child / Child() / getMainClass : " + this.getMainClass);
this.monitor();
}
return;
}
public function monitor():void{
/*偵聽Main.LOADED 之載入完成事件*/
this.addEventListener(getMainClass.LOADED,loadedHandler);
this.addEventListener(Event.ADDED_TO_STAGE,addedToStage);
return;
}
public function loadedHandler(event:Event):void{
this.removeEventListener(getMainClass.LOADED,loadedHandler);
trace("@Child / loadedHandler() / event.type : " + event.type);
/*取得父類別實體*/
var myParent:* = getMainClass(this.parent);
trace("@Child / loadedHandler() / myParent : " + myParent);
/*調用Main的hello()方法*/
trace("***********************************");
trace("從Child調用Main的hello()方法 - 以下這行");
var message:String = myParent.hello();
trace(message);
trace("***********************************");
/*A法 : 使用 ApplicationDomain.currentDomain.getDefinition()方法*/
/*取得Ball的類別參照,調用其建構式*/
/*var getBallClass:Class = ApplicationDomain.currentDomain.getDefinition("Ball") as Class;*/
/*B法 : 使用getDefinitionByName(name:String):Object,取得Ball的類別參照,代表父層類別可見度ok*/
var getBallClass:Class = getDefinitionByName("Ball") as Class
trace("@Child / loadedHandler() / getBallClass : " + getBallClass);
var myParentBall:* = new getBallClass(160,200);
trace("@Child / loadedHandler() / myParentBall : " + myParentBall);
this.parent.addChild(myParentBall);
return;
}
public function addedToStage(event:Event):void{
this.removeEventListener(Event.ADDED_TO_STAGE,addedToStage);
this.addEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
return;
}
public function removedFromStage(event:Event):void{
this.removeEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
return;
}
public function welcome(_name:String):String {
return "@Child : Hello, " + _name;
}
}
}
Ball.as
package {
import flash.display.SimpleButton;
import flash.events.Event;
public class Ball extends SimpleButton {
public var thisX:Number;
public var thisY:Number;
public function Ball(_x:Number,_y:Number) {
this.addEventListener(Event.ADDED_TO_STAGE,addedToStage);
this.thisX = _x;
this.thisY = _y;
return;
}
public function addedToStage(event:Event):void{
this.removeEventListener(Event.ADDED_TO_STAGE,addedToStage);
this.addEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
this.x = this.thisX;
this.y = this.thisY;
return;
}
public function removedFromStage(event:Event):void{
this.removeEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
return;
}
/*此例, Ball類別的這個ballFunc()方法,將在child.swf 被Main.swf 載入後,被Child類別實體調用*/
public function ballFunc():void{
trace("@Ball / ballFunc : I am from Ball Class");
}
}
}
值得注意這件事......
若把Main類別的Main建構函數的以下這行刪掉 :
var ldrContext: LoaderContext = new LoaderContext(false,ApplicationDomain.currentDomain);
且把Main類別的Main建構函數的 ldr.load(req,ldrContext); 的 「,ldrContext」刪掉
[Ctrl+enter]測試影片, 將出現錯誤
ReferenceError: Error #1065: 變數 Child 未定義。
at global/flash.utils::getDefinitionByName()
at Main/completeHandler()
可見, 透過LoaderContext類別物件指定ApplicationDomain.currentDomain
將被載入child.swf 的公用類別定義置於目前載入器根swf所處的應用程式網域
就是本實例能夠正確運作的最大關鍵 ─ 父層子層雙向取用類別定義
若有人真的仔細看了code, 將會發現......
在main與Child裡, 由於處於父層子層彼此類別定義的透視度中
所以, 皆採用 [B法] 來取得對象的類別參照
即 getDefinitionByName(name:String):Object
然而, [A法] 的 ApplicationDomain.currentDomain.getDefinition()方法
則是,未取得父層子層彼此類別定義的透視度時的最佳利器.
透過 ApplicationDomain類別的[靜態]屬性currentDomain傳回目前應用程式網域物件(ApplicationDomain物件),
再調用getDefinition()方法取得類別參照.
很大的好處是,因為 ApplicationDomain.currentDomain為靜態屬性,
可在父層或子層直接呼叫, 達到子層取得父層各類別的目的
否則還真難達成.
前此, 那個 [大誤] 的例子, 最大的錯誤在於......
誤以為從相同網域載入的swf, 不需設定LoaderContext, 就立即與載入器根swf擁有相同應用程式網域
因此彼此擁有相互類別可見度. 其實不然啦.
再者, 沒有將main.as和child.as分開在不同套件目錄
則造成測試的混淆. 大誤阿 !!!



4 則留言:
發現如果LoaderContext的application參數如果使用new ApplicationDomain()也能正常執行,且,如果不同網域下有相同的class名稱,使用application參數使用ApplicationDomain.currentDomain會造成混淆,意指getDifinitionByName只會去抓ApplicationDomain.currentDomain裡的那個Class,所以使用ApplicationDomain.currentDomain必須確保Main Library與External Library命名不衝突,否則必須在external的LoaderContext建立新網域
fp版本也有差,小弟在fp9下測試,將load的loadercontext參數拿掉,依然可以正常執行,當然,無法取得child,換到fp10以上版本,測試就會如大大測試結果那樣
fp版本是我弄錯了= =上面那篇當我沒說…sorry,不過上上篇的沒錯
補充第一篇,我說的getDefinitionByName會混淆是指當 LoaderContext的applicationDomain設定是Main.loaderInfo.applicationDomain or ApplicationDomian.current時,在child中使用getDefinitionByName即會去抓父網域的相同名稱Class,而子網域的同名Class就...長腳跑了
張貼留言