5 Replies Latest reply on Mar 1, 2011 11:30 PM by FlippieScholtz

    Module variables lost upon 2nd load

    FlippieScholtz

      Hi

       

      I am using Flex SDK 4.1 and Flash Builder 4, with the Mate framework.

      My main application uses the following process to load / unload modules:

      1) ModuleManager.getModule(moduleURLl)

      2) moduleInfo.load() on moduleInfo returned at 1)

      3) moduleInfo.factory.create() when the ModuleEvent.READY is dispatched.

      4) To unload, I just do moduleInfo.unload().

       

      My problem:

      One of the modules initializes some private variables in the creationComplete handler of the <mx:Module> tag which get used later in the module.

      When the module is loaded for the first time, everything works fine and the variables retain their values after the initialization.

      However, any subsequent loads of the module (after being unloaded / loaded again) results in the following weird issue:

       

      The creationComplete handler gets fired as normal. At the end of the handler function I check the private variables and they have the correct values as set up by the handler.

      BUT: Right after the handler completes, all the variables inexplicably revert back to null. (or the initial values assigned in their definition on the class level).

      So all the variables are correctly initialized, but they lose the data as soon as the handler completes.

      All these variables are private vars defined right after the import statements at the very top of my <mx:Script>, so they should retain their values outside of individual functions.

       

      It's just weird that it only happens on subsequent loads of the module. The first load works fine.

      The flex 4.1 SDK warns me about all of my modules being directly referenced and linked into the main application...which is not correct because I don't have inter-module references. Could this have something to do with it? I can't understand why it only happens the 2nd time and not the first?

       

      Thanks

        • 1. Re: Module variables lost upon 2nd load
          Flex Rock Level 1

          Hi Flippie,

                              Can you post a sample your code.

           

           

          thanks,

          Jayagopal.

          • 2. Re: Module variables lost upon 2nd load
            Darrell Loverin Level 4

            >>The flex 4.1 SDK warns me about all of my modules being directly referenced and linked into the main application...which is not correct because I don't have inter-module references. Could this have something to do with it? I can't understand why it only happens the 2nd time and not the first?

             

            Create a link report for your main application and see if the module has been linked into the application.

             

             

             

            -Darrell

            • 3. Re: Module variables lost upon 2nd load
              FlippieScholtz Level 1

              Hi Jayagopal

               

               

               

              I have simplified my code somewhat to highlight the basic issue. This issue

              is probably the root cause of all my other

               

              issues.

               

              I use the Presentation Model pattern of the mate framework. (I have also

              posted this on the mate framework websites'

               

              forum).

               

               

               

              Here goes a clearer explanation of the issue with some code examples:

               

               

               

              Hi

               

              I'm using Flex 4.0 . I am following the Presentation Model Pattern.

              I load /unload modules using Flex's ModuleManager class. (Doing every

              required step like listening for the READY event and

               

              using a factory to create the module, etc.)

               

              I'm having a very weird problem. All of my modules has a presentation model

              injected into it. In the creationComplete

               

              handler of one particular module, I call a function in the model which fires

              off an event. The event map then does a RPC

               

              call (RemoteObjectInvoker) to fetch the data. In the resultHandlers tag it

              does an EventAnnouncer which is tied to a

               

              function in my module view through a ListenerInjector in the same map.

              So upon return of the RPC, the function drawTimeTypes gets called in my

              view. This function then sets the selectedIndex of

               

              a conboBox to a certain value.

              The first time I load the module, everything works as expected. The RPC

              returns and the Listener fires off the

               

              drawTimeTypes function and the comboBox is updated correctly. However, on

              the second, and any subsequent loads of the

               

              module, a VERY strange thing happens:

              The event gets fired, the RPC returns and the listener function is called (I

              verify it through the Alert.show in the

               

              function). BUT...the comboBox does not update. It stays at selectedIndex =

              0. I know that the selectedIndex line does

               

              execute, because I see the Alert, but the property doesn't change. It's as

              if all the class variables in the view revert

               

              back to their original values right after the drawTimeTypes finishes. And it

              ONLY happens on subsequent loads of the

               

              module, NOT the first time...

               

              My view (which is a module):

               

              code

              <?xml version="1.0" encoding="utf-8"?>

              <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"

              width="100%" height="100%"

               

              xmlns:views="com.SecSA.timetrack.views.*" creationComplete="init();"

              xmlns:maps="com.SecSA.timetrack.maps.*"

               

              xmlns:controls="controls.*">

              <maps:TimetrackMap dispatcher=""/>

              <mx:Script>

              <![CDATA[

              import com.SecSA.timetrack.events.TimetrackEvent;

              import com.SecSA.timetrack.models.TimetrackModel;

               

              import mx.collections.ArrayCollection;

              import mx.controls.Alert;

               

              Bindable public var model:TimetrackModel;

               

              public function init():void {

              model.getTimeTypes();

              }

               

              public function drawTimeTypes(event:TimetrackEvent=null):void {

              timeTypesCombo.selectedIndex = 2;

              Alert.show("rpc returned and comboBox set.");

              }

              ]]>

              </mx:Script>

              <mx:HBox width="100%">

              <mx:ComboBox id="timeTypesCombo">

              <mx:dataProvider>

              <mx:Array>

              <mx:String>Type 1</mx:String>

              <mx:String>Type 2</mx:String>

              <mx:String>Type 3</mx:String>

              <mx:String>Type 4</mx:String>

              </mx:Array>

              </mx:dataProvider>

              </mx:ComboBox>

              </mx:HBox>

              </mx:Module>

              /code

               

               

               

              And my map event handler (called in creationComplete of view via model):

               

              (This is in TimetrackMap.mxml which you can see included in the view above -

              in the maps namespace).

               

              code

               

              <EventAnnouncer generator=""

              type="{TimetrackEvent.DRAW_TIME_TYPES}"/>

              </resultHandlers>

              </RemoteObjectInvoker>

              </EventHandlers>

              /code

               

              And the injector injecting the model as well as the listener for event fired

              in EventAnnouncer above:

              code

              <Injectors target="" debug="false">

              <ObjectBuilder generator=""

              constructorArguments="{scope.dispatcher}"/>

              <PropertyInjector targetKey="model" source=""/>

               

              /code

               

              And finally, if the module loading code might be of any relevance: (This

              happens in the 'main' part of my application:)

               

              I load the module by URL of the SWF and then I add it as a child to my main

              container. Note it gets unloaded and reloaded

               

              every time the user chooses a module.

              code

              public function loadModule(urlOfModule:String):void {

              if(moduleContainer != null){

              if(moduleContainer.numChildren > 1){

              moduleInfo.unload();

              moduleContainer.removeChild(currentModule);

              }

              }

              moduleInfo = ModuleManager.getModule(moduleURL);

              moduleInfo.addEventListener(ModuleEvent.READY, moduleReady);

              moduleInfo.addEventListener(ModuleEvent.PROGRESS, moduleProgress);

              moduleInfo.load(new ApplicationDomain(ApplicationDomain.currentDomain));

               

              public function moduleReady(event:ModuleEvent=null):void {

              progressBox.includeInLayout = false;

              progressBox.visible = false;

              currentModule = moduleInfo.factory.create() as Module;

              moduleContainer.addChild(currentModule);

              }

               

               

              /code

               

              I simplified the view to make the issue clearer, but in reality I have lots

              of private variables in my view that all lose

               

              their values when drawTimeTypes returns. They get set, I verify it. But they

              just inexplicably revert back to the original

               

              definition value or null when the method returns...I'm at a loss.

               

              Thanks!

              • 4. Re: Module variables lost upon 2nd load
                FlippieScholtz Level 1

                OK, I've narrowed down the issue even further through some trial and error:

                 

                 

                If I ditch the model (and RPC call) completely and I just dispatch the event

                directly in the view, it works as required...comboBox is updated every time

                the module is loaded.

                 

                 

                So I still use the Mate map to inject the Listener into the view, but I just

                fire the event directly in the view instead of it being fired in the

                EventMap on return of the RPC:

                 

                 

                Obviously, I need to run the RPC and the event must fire on the return of

                the RPC, so this is an unacceptable workaround, but perhaps it helps someone

                get to the bottom of the problem.

                 

                 

                Here is my updated view code which works: (The only difference is that the

                init() function dispatches the DRAW event directly instead of going through

                to the RPC first).

                 

                 

                 

                <?xml version="1.0" encoding="utf-8"?>

                 

                <mx:Module  xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"

                width="100%" height="100%" xmlns:views="com.SecSA.timetrack.views.*"

                creationComplete="init();" xmlns:maps="com.SecSA.timetrack.maps.*"

                xmlns:controls="controls.*">

                 

                <maps:TimetrackMap dispatcher=""/>

                 

                <mx:Script>

                 

                <![CDATA[

                 

                import com.SecSA.timetrack.events.TimetrackEvent;

                 

                import com.SecSA.timetrack.models.TimetrackModel;

                 

                import mx.collections.ArrayCollection;

                 

                import mx.controls.Alert;

                 

                public var model:TimetrackModel;

                 

                public function init():void {

                 

                var event:TimetrackEvent = new

                TimetrackEvent(TimetrackEvent.DRAW_TIME_TYPES);

                 

                this.dispatchEvent(event);

                 

                }

                 

                public function drawTimeTypes(event:TimetrackEvent=null):void {

                 

                timeTypesCombo.selectedIndex = 2;

                 

                Alert.show("rpc returned and comboBox set.");

                 

                }

                 

                ]]>

                 

                </mx:Script>

                 

                <mx:HBox width="100%">

                 

                <mx:ComboBox id="timeTypesCombo">

                 

                <mx:dataProvider>

                 

                <mx:Array>

                 

                <mx:String>Type 1</mx:String>

                 

                <mx:String>Type 2</mx:String>

                 

                <mx:String>Type 3</mx:String>

                 

                <mx:String>Type 4</mx:String>

                 

                </mx:Array>

                 

                </mx:dataProvider>

                 

                </mx:ComboBox>

                 

                </mx:HBox>

                 

                </mx:Module>

                 

                /code

                • 5. Re: Module variables lost upon 2nd load
                  FlippieScholtz Level 1

                  Hi.

                   

                  I seem to have solved the problem by using Danny Kopping's extension of the ModuleLoader class. (http://ria-coder.com/blog/truly-cached-flex-modules).

                  The problem was most probably related to some internal module caching issue.

                   

                  I don't want to speculate about the causes, but I suppose the Mate binding system and Flex's ModuleLoader doesn't play well together under certain specific circumstances.

                   

                  Thanks for everybody's attempts to help.