0

私はこれについてグーグル全体を探してきましたが、良い答えが見つかりません。私はflex 4を使用し、モジュールを使用してエアアプリを構築しています(これは大きなプロジェクトであるため、モジュールがたくさんあります)。popupmanager によって呼び出される titlewindow にモジュールをロードすることはできましたが、titlewindow を閉じると、モジュールはアンロード (ガベージ) されません - flasbuilder のプロファイラーを使用してこれを確認しました。

これが私のコードです。プロジェクトで多くのことを行う前に、モジュールを使用して正しい方向に進んでいるかどうかを知る必要があります。

ありがとうございます

Main APP: MXML

<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                   xmlns:s="library://ns.adobe.com/flex/spark"
                   xmlns:mx="library://ns.adobe.com/flex/mx"
                   xmlns:tblusersservice="services.tblusersservice.*"
                   xmlns:valueObjects="valueObjects.*"
                   xmlns:tbluserservice="services.tbluserservice.*"
                   width="100%" height="100%" applicationComplete="checkForUpdate()" preinitialize="nativeWindow.maximize();" currentState="login">

<fx:Script source="includes/_loadtracker.as"/>



<s:Panel id="panelmain" includeIn="mainmenu" left="5" width="100%" height="100%" resizeEffect="Resize" title="Main menu">

    <s:Image id="companymenu" right="15" top="130" width="118" height="93" buttonMode="true"
             click="loadmodule('mod_company', 'Company Information', 931, 446);" source="assets/company.png" useHandCursor="true"/>


</s:Panel>



</s:WindowedApplication>




_loadtracker.as:

// ActionScript file
import flash.filesystem.*;
import flash.events.ErrorEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.*;
import air.update.ApplicationUpdaterUI;
import air.update.events.UpdateEvent;
import mx.controls.Alert;       
import mx.managers.PopUpManager;
import mx.rpc.events.ResultEvent;
import spark.components.TitleWindow;
import valueObjects.*;
import flash.desktop.NativeApplication;



// Open the pop-up window.
private function loadmodule(modname:String, modtitle:String, modwidth:int, modheight:int):void {
// Create a non-modal TitleWindow container.
settings.moduletoload = modname;
var titleWindow:TitleWindow=
    PopUpManager.createPopUp(this, showmodules, true) as TitleWindow;
titleWindow.title = modtitle;
titleWindow.width = modwidth;
titleWindow.height = modheight + 35;
    PopUpManager.centerPopUp(titleWindow);
}





showmodules.mxml

<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009" 
           xmlns:s="library://ns.adobe.com/flex/spark" 
           xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="400"  creationComplete="initModule()" close="handleCloseEvent()">

<fx:Script>
    <![CDATA[

        import mx.controls.Alert;
        import mx.core.IVisualElement;
        import mx.events.ModuleEvent;
        import mx.managers.PopUpManager;
        import mx.modules.IModuleInfo;
        import mx.modules.ModuleManager;
        import mx.rpc.events.ResultEvent;
        import services.tbluserservice.*;

        public var info:IModuleInfo;
        public var modclosed:Boolean = false;

        private function initModule():void {
            this.addEventListener("foobar", handleCloseEventmodule);

            info = ModuleManager.getModule("/modules/"+settings.moduletoload+".swf");
            info.addEventListener(ModuleEvent.READY, modEventHandler);           

            info.load(null, null, null, moduleFactory);
        }

        /* Add an instance of the module's class to the display list. */        
        private function modEventHandler(e:ModuleEvent):void {

            this.addElement(info.factory.create() as IVisualElement);
        }

        // Handle the close button and Cancel button.
        public function handleCloseEvent():void {

                PopUpManager.removePopUp(this);
                info.unload();
                info.release();
                info = null;

        }

    ]]>
</fx:Script>

<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:TitleWindow>




mod_company.mxml

<s:Module xmlns:fx="http://ns.adobe.com/mxml/2009"
      xmlns:s="library://ns.adobe.com/flex/spark"
      xmlns:mx="library://ns.adobe.com/flex/mx"
      xmlns:tblcompanyservice="services.tblcompanyservice.*"
      xmlns:valueObjects="valueObjects.*"
      width="931" height="446"
      creationComplete="LoadData()">
<fx:Script>
    <![CDATA[
        import mx.events.FlexEvent;

        protected function dataGrid_creationCompleteHandler(event:FlexEvent):void
        {
            getAllTblcompanyResult.token = tblcompanyService.getAllTblcompany();
        }

    ]]>
</fx:Script>

<fx:Script source="../includes/_company.as"/>

<fx:Declarations>
    <tblcompanyservice:TblcompanyService id="tblcompanyService"
                                         fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)"
                                         showBusyCursor="true"/>
    <s:CallResponder id="getTblcompanyByIDResult" fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)"
                     result="tblcompany = getTblcompanyByIDResult.lastResult as Tblcompany"/>
    <valueObjects:Tblcompany id="tblcompany"/>
    <s:CallResponder id="updateTblcompanyResult"/>
    <s:CallResponder id="getAllTblcompanyResult"/>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Label x="81" y="41" text="COMPANY NAME"/>
<s:Label x="81" y="71" text="ADDRESS"/>
<s:Label x="83" y="131" text="CITY"/>
<s:Label x="83" y="161" text="STATE"/>
<s:Label x="83" y="191" text="ZIP"/>
<s:Label x="83" y="221" text="COUNTRY"/>
<s:Label x="582" y="41" text="TELEPHONE"/>
<s:Label x="582" y="71" text="FAX"/>
<s:Label x="582" y="102" text="WATTS"/>
<s:Label x="83" y="276" text="OWNER"/>
<s:Label x="83" y="324" text="LOGO PATH"/>
<s:TextInput id="fNameTextInput" x="185" y="32" width="323" text="{tblcompany.fName}"/>
<s:TextInput id="faddressTextInput" x="185" y="62" width="256" text="{tblcompany.faddress}"/>
<s:TextInput id="faddress2TextInput" x="185" y="92" width="256" text="{tblcompany.faddress2}"/>
<s:TextInput id="fcityTextInput" x="185" y="122" width="256" text="{tblcompany.fcity}" textAlign="left"/>
<s:TextInput id="fstateTextInput" x="185" y="152" width="256" text="{tblcompany.fstate}"/>
<s:TextInput id="fzipTextInput" x="185" y="182" width="81" text="{tblcompany.fzip}"/>
<s:TextInput id="fcountryTextInput" x="185" y="212" width="256" text="{tblcompany.fcountry}"/>
<s:TextInput id="ftelTextInput" x="701" y="32" text="{tblcompany.ftel}"/>
<s:TextInput id="ffaxTextInput" x="701" y="62" text="{tblcompany.ffax}"/>
<s:TextInput id="fwattsTextInput" x="701" y="92" text="{tblcompany.fwatts}"/>
<s:TextInput id="fownerTextInput" x="185" y="266" width="418" text="{tblcompany.fowner}"/>
<s:TextInput id="flogopathTextInput" x="185" y="314" width="644" text="{tblcompany.flogopath}"/>
<s:TextInput id="fidTextInput" x="224" y="379" text="{tblcompany.fid}" visible="false"/>
<s:Button id="button" x="79" y="379" label="Save" click="button_clickHandler(event)"/>
<s:DataGrid id="dataGrid" x="158" y="242"
            creationComplete="dataGrid_creationCompleteHandler(event)" requestedRowCount="4">
    <s:columns>
        <s:ArrayList>
            <s:GridColumn dataField="fid" headerText="fid"></s:GridColumn>
            <s:GridColumn dataField="fName" headerText="fName"></s:GridColumn>
            <s:GridColumn dataField="fowner" headerText="fowner"></s:GridColumn>
            <s:GridColumn dataField="faddress" headerText="faddress"></s:GridColumn>
            <s:GridColumn dataField="faddress2" headerText="faddress2"></s:GridColumn>
            <s:GridColumn dataField="fcity" headerText="fcity"></s:GridColumn>
            <s:GridColumn dataField="fzip" headerText="fzip"></s:GridColumn>
            <s:GridColumn dataField="fstate" headerText="fstate"></s:GridColumn>
            <s:GridColumn dataField="fcountry" headerText="fcountry"></s:GridColumn>
            <s:GridColumn dataField="ftel" headerText="ftel"></s:GridColumn>
            <s:GridColumn dataField="ffax" headerText="ffax"></s:GridColumn>
            <s:GridColumn dataField="fwatts" headerText="fwatts"></s:GridColumn>
            <s:GridColumn dataField="flogopath" headerText="flogopath"></s:GridColumn>
            <s:GridColumn dataField="femail" headerText="femail"></s:GridColumn>
        </s:ArrayList>
    </s:columns>
    <s:typicalItem>
        <fx:Object faddress="faddress1" faddress2="faddress21" fcity="fcity1"
                   fcountry="fcountry1" femail="femail1" ffax="ffax1" fid="fid1"
                   flogopath="flogopath1" fName="fName1" fowner="fowner1" fstate="fstate1"
                   ftel="ftel1" fwatts="fwatts1" fzip="fzip1"></fx:Object>
    </s:typicalItem>
    <s:AsyncListView list="{getAllTblcompanyResult.lastResult}"/>
</s:DataGrid>
</s:Module>




_company.as


// ActionScript file
//import flash.desktop.NativeApplication;
import flash.events.MouseEvent;
import flash.events.Event;
import mx.controls.Alert;
//import mx.core.Application;
//import mx.core.mx_internal;
import services.tblcompanyservice.*;
import valueObjects.*;

protected function LoadData():void {
getTblcompanyByIDResult.token = tblcompanyService.getTblcompanyByID(parseInt("1"));
}

protected function button_clickHandler(event:MouseEvent):void {
tblcompany.fid = parseInt(fidTextInput.text);

tblcompany.fName = fNameTextInput.text;
tblcompany.fowner = fownerTextInput.text;
tblcompany.faddress = faddressTextInput.text;
tblcompany.faddress2 = faddress2TextInput.text;
tblcompany.fcity = fcityTextInput.text;
tblcompany.fzip = fzipTextInput.text;
tblcompany.fstate = fstateTextInput.text;
tblcompany.fcountry = fcountryTextInput.text;
tblcompany.ftel = ftelTextInput.text;
tblcompany.ffax = ffaxTextInput.text;
tblcompany.fwatts = fwattsTextInput.text;
tblcompany.flogopath = flogopathTextInput.text;
tblcompany.femail = "";
updateTblcompanyResult.token = tblcompanyService.updateTblcompany(tblcompany);
//Alert.show("Modifications saved");
//this.dispatchEvent(new Event("foobar", true));
}
4

2 に答える 2

0

Flex モジュールのアンロードは、歴史的に問題がありました。Flex 4 と私は、4.5 が私たちの生活を楽にするために根底にある問題を少しずつ取り除き始めたと思います。

メイン アプリ内の何かがモジュール内のオブジェクトへの参照を保持している場合、モジュールのアンロードが妨げられます。これには多くの方法があります。Flex は、動作方法が原因で、これらの問題の一部を引き起こす可能性があります。しかし、主要な頭痛の種は軽減されました (ただし、Flex 4.5 を使用していることを確認してください)。

今このことを考えているあなたは間違いなく賢明です。モジュールを使用するかどうかの選択ではなく、モジュールがアンロードされていることを確認します。

私がリンクした記事は、Flex SDK 開発者からの古い投稿ですが、これらの問題のいくつかはもはや存在しない可能性がありますが、その概念は啓発的であるはずです。

編集

さらに詳しく調べてみると、目に飛び込んできたものの 1 つだけが注目に値すると思われます。

  • モジュール内のスクリプト タグには、スタイルがもたらす可能性があるのと同じ問題が発生する可能性があります (また、ニシンである可能性もあります)。このスクリプトを使用する最初のクラスは、Flex によって内部的にスクリプトと永続的に関連付けられる可能性があるという考えです。そのクラスがモジュールの場合、アンロードされません。WindowedApplicationテストとして、スクリプト タグをクラスで宣言することもできます (使用されていませんが)。

私が考えたもう 1 つのことは、ビュー内のバインド可能な変数です。しかし、さらに調べてみると、それらがどのようにメモリリークを引き起こしているのかわかりません。

于 2012-06-08T23:04:40.393 に答える
0

問題は、毎回新しい TitleWindow を作成していることだけであり、TitleWindow は、モジュール ローダーを介して読み込まれるモジュールにイベント リスナーを追加し、決して削除しないことだと思います。理論的には、PopupManager.removePopup も毎回 TitleWindow を逆参照する必要がありますが、正直なところ、この機能をグローバル/静的クラスとして記述する人は、おそらく他の場所での適切な実践に準拠しているとは信じられないため、おそらく使用する必要がありますF3 キーを押して PopupManager のコードを調べ、追加したイベント リスナーが削除され、タイトル ウィンドウへの参照が null になっていることを確認します。これは静的なクラスであるため、何かが話しかけると、適切に逆参照しないと、アプリの寿命が尽きるまで残ります。

次に、既に読み込まれているモジュールがある場合でも、モジュールのインスタンスを手動で作成します。ローダーを手放すためにいくつかのこと (イベント リスナーの削除以外) を行いますが、手動で作成されたインスタンスを解放することはありません。物事を少し単純化するために、追加のモジュールを作成する代わりに、ロードされたモジュールを追加してみてください。

もう 1 つの提案は、データ ストアの代わりにビュー要素を使用しないことです。したがって、VO にバインドする代わりに、VO を取得したら、VO からフィールドに入力します。何か変更があった場合は、VO の値に基づいて VO を更新します。これによりコードが少し増えますが、1 つには、データが常に最新であることがわかります。別の例では、データは必要に応じて、ビューとは無関係に移動できます。しかし、これは、バインディングが VO をメモリに保持している可能性を排除するのに役立つ可能性があることの 1 つです。

また、コードの周囲にかすかな納屋の匂いを発生させる行為がいくつかありますが、これらも問題の原因となる可能性があります。たとえば、タイトル ウィンドウのサブクラスには、設定を指定していなくても、設定への参照があるようです。これは、設定が実際には静的なクラスであり、クラスが大文字で始まるという命名規則を無視したことを示唆しています。さらに重要なことは、このようなバック チャネルで通信が行われている場合、コードを見て、保持している何かへの参照を何らかの形で設定に与えたところで何かが起こっていないと判断する方法がないことです。に。

また、宣言されていない変数 modulefactory のように見えるものもありますが、これはおそらく、TitleWindow と同じパッケージにある不適切な名前のクラスだと思います (そのため、インポート ステートメントはありません)。簡単なアドバイス: フォーラムで助けが必要な場合は、命名規則に従うことで、助けを求めている人があなたが行ったことを簡単に解明できるようになります。この場合、OOP 通信のベスト プラクティスを回避する「不正な」機能が存在する場所がある可能性があり、名前の付け方が原因で特定が容易ではありません。

しかし最終的には、モジュールのコピーを 1 つだけにしてイベント リスナーを削除すれば、モジュールを手放すことができ、VO を解放できるはずです。

于 2012-06-10T02:04:13.980 に答える