使用應用程式網域

Flash Player 9 以及更新的版本,Adobe AIR 1.0 以及更新的版本

ApplicationDomain 類別的目的是用於儲存 ActionScript 3.0 的定義表格。SWF 檔中的所有程式碼都定義為存在應用程式網域中。您可以使用應用程式網域,分割位於相同安全性網域中的類別。這麼做能允許相同的類別具有多項定義,並讓子系重新使用父輩定義。

您可以在使用 Loader 類別 API 載入以 ActionScript 3.0 撰寫的外部 SWF 檔時,使用應用程式網域 (請注意,當您載入以 ActionScript 1.0 或 ActionScript 2.0 撰寫的影像或 SWF 檔時,將無法使用應用程式網域)。所有包含在載入類別中的 ActionScript 3.0 定義都會儲存在應用程式網域中。載入 SWF 檔時,您可以將 LoaderContext 物件的 applicationDomain 參數設定為 ApplicationDomain.currentDomain,指定將該檔案包含在與 Loader 物件檔案相同的應用程式網域中。藉由將載入的 SWF 檔置於相同的應用程式網域中,便可以直接存取其類別。如果您要載入包含內嵌媒體 (透過媒體相關類別名稱進行存取) 的 SWF 檔,或是要存取所載入 SWF 檔的方法,這就十分有用。

下列範例假設它可以存取不同的 Greeter.swf 檔案,該檔案定義公用方法 welcome():

package 
{ 
    import flash.display.Loader; 
    import flash.display.Sprite; 
    import flash.events.*; 
    import flash.net.URLRequest; 
    import flash.system.ApplicationDomain; 
    import flash.system.LoaderContext; 
 
    public class ApplicationDomainExample extends Sprite 
    { 
        private var ldr:Loader; 
        public function ApplicationDomainExample() 
        { 
            ldr = new Loader(); 
            var req:URLRequest = new URLRequest("Greeter.swf"); 
            var ldrContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain); 
            ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler); 
            ldr.load(req, ldrContext);     
        } 
        private function completeHandler(event:Event):void 
        { 
            var myGreeter:Class = ApplicationDomain.currentDomain.getDefinition("Greeter") as Class; 
            var myGreeter:Greeter = Greeter(event.target.content); 
            var message:String = myGreeter.welcome("Tommy"); 
            trace(message); // Hello, Tommy 
        } 
    } 
}

另請參閱適用於 Adobe Flash Platform 的 ActionScript 3.0 參考中的 ApplicationDomain 類別範例。

當您處理應用程式網域時,其它要注意的事項包括:

  • SWF 檔中的所有程式碼都定義為存在應用程式網域中。「目前的網域」是指您的主應用程式在其中執行的網域。「系統網域」則包含所有的應用程式網域,其中包括目前的網域,也就是包含了所有的 Flash Player 類別。

  • 所有的應用程式網域,除了系統網域之外,都具有相關的父網域。您的主應用程式之應用程式網域的父網域,就是系統網域。只有在其父輩尚未定義載入的類別時,才會定義這些類別。因此,您不能以較新的定義覆寫載入類別的定義。

下圖顯示在單一網域 domain1.com 中,從各種不同 SWF 檔載入內容的應用程式。根據所載入的內容而定,可能會用到不同的應用程式網域。下方的文字說明在應用程式中用來為每一個 SWF 檔設定適當應用程式網域的邏輯。

檢視完整大小的圖形
A.
用法 A

B.
用法 B

C.
用法 C

主應用程式檔案為 application1.swf,它包含會從其它 SWF 檔載入內容的 Loader 物件。在此案例中,目前的網域是「應用程式網域 1」。用法 A、用法 B 和用法 C 各說明不同的技巧,可用來在應用程式中為每一個 SWF 檔設定適當的應用程式網域。

用法 A
藉由建立系統網域的子系,分割子 SWF 檔。在圖中,「應用程式網域 2」是建立做為系統網域的子網域,application2.swf 檔會載入至「應用程式網域 2」中,而其類別定義就會從 application1.swf 所定義的類別中分割出來。

此技巧的其中一項用法,就是讓舊的應用程式以動態方式載入較新版的相同應用程式,而不造成衝突。沒有發生衝突的原因,是因為雖然使用了相同的類別名稱,但是類別都已經分割而位於不同的應用程式網域中。

下列程式碼會建立系統網域子系的應用程式網域,並開始使用該應用程式網域載入 SWF:

var appDomainA:ApplicationDomain = new ApplicationDomain(); 
 
var contextA:LoaderContext = new LoaderContext(false, appDomainA); 
var loaderA:Loader = new Loader(); 
loaderA.load(new URLRequest("application2.swf"), contextA);

用法 B:
將新的類別定義新增至目前的類別定義。module1.swf 的應用程式網域設定為目前的網域 (應用程式網域 1),這可讓您在應用程式目前的類別定義集中,加入新的類別定義。這可以用來做為主應用程式的執行階段共享元件庫。所載入的 SWF 會視為執行階段共享元件庫 (RSL)。您可以使用這項技巧,在應用程式開始之前,預先載入器載入 RSL。

下列程式碼會載入 SWF,並將其應用程式網域設定為目前的網域:

var appDomainB:ApplicationDomain = ApplicationDomain.currentDomain; 
 
var contextB:LoaderContext = new LoaderContext(false, appDomainB); 
var loaderB:Loader = new Loader(); 
loaderB.load(new URLRequest("module1.swf"), contextB);

用法 C:
透過建立目前網域的新子網域,使用父項目的類別定義。module3.swf 的應用程式網域是目前網域的子網域,這個子網域會使用父輩所有類別的版本。此技巧的其中一項用法,是可以做為具有多重螢幕之多樣化網頁應用程式 (Rich Internet Application,RIA) 的模組,此模組會載入為主應用程式的子系,並使用主應用程式的類型。如果您能確保所有類別都一定會升級以與舊版相容,而且載入內容的應用程式一定會比它所載入的內容更新,則子系將會使用父輩版本。如果您確定不會繼續參考子 SWF,則具有新的應用程式網域也可讓您取消載入所有的類別定義,以便進行記憶體回收。

這項技巧可讓載入模組共享載入器的 Singleton 物件和靜態類別成員。

下列程式碼會建立目前網域的新子網域,並使用該應用程式網域開始載入 SWF:

var appDomainC:ApplicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain); 
 
var contextC:LoaderContext = new LoaderContext(false, appDomainC); 
var loaderC:Loader = new Loader(); 
loaderC.load(new URLRequest("module3.swf"), contextC);