Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Better startup idiom  (Read 16548 times)
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« on: October 20, 2007, 11:35:45 »

With the currently documented idiom, to start up a PureMVC application built in Flex or AIR we:

1) Allow the MXML view to be built from the Application or WindowedApplication tag,
2) In a script block, we initialize a variable with the Singleton instance of the Facade, creating the Model, View and Controller
3) On the creationComplete event for the application, we create a Notification with a name like STARTUP,
4) Call the notifiyObservers method of the facade, passing the Notification and a reference to the Application itself
5) A StartupCommand is triggered which prepares first the Model and then the View.

This leaves you with a top level app looking similar to:
:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal"
    xmlns:view="com.me.myapp.*"
    creationComplete="initApp()" >

    <mx:Script>
        <![CDATA[
            import org.puremvc.patterns.observer.Notification;
            import com.me.myapp.ApplicationFacade;
           
            private var facade:ApplicationFacade = ApplicationFacade.getInstance();
            private function initApp():void
            {
                facade.notifyObservers( new Notification( ApplicationFacade.STARTUP, this ) );
            }           
        ]]>
    </mx:Script>
   
    <!-- Top level controls and containers of app go here-->

</mx:Application>


That places more knowledge of the PureMVC system than I'd like in the MXML Application, which is just a view component, really, and should be constrained by the same rule we apply to all view components, which is to make them portable by reducing their knowledge of the system they're attached to.

But we've got to get the party started somehow. Here's how to do it with way less knowledge of the PureMVC apparatus.

1) Add a public method called 'startup' to your concrete Facade which accepts a reference to the Application
2) In the script block of the Application, keep the initialized facade variable, but get rid of the 'initApp' method.
3) In the creationComplete handler of the Application tag, simply call 'facade.startup(this)'

This leaves you with this method in your ApplicationFacade:
:

public function startup( app:Object ):void
{
    notifyObservers( new Notification( STARTUP, app ) );
}           


And an MXML Application that looks like this:
:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal"
    xmlns:view="com.me.myapp.*"
    creationComplete="facade.startup(this)" >

    <mx:Script>
        <![CDATA[
            import com.me.myapp.ApplicationFacade;
            private var facade:ApplicationFacade = ApplicationFacade.getInstance();
        ]]>
    </mx:Script>
   
    <!-- Top level controls and containers of app go here-->

</mx:Application>


This method works just as well in Flash or FlashLite (yes, an AS2 port is working and coming soon) where we can just call it from the actions of frame 1 of the main movie. There it may this simple:

:

import com.me.myapp.ApplicationFacade;
ApplicationFacade.getInstance().startup( _root );


This works well for me and is definitely the recommended way to startup your application. I will be updating the Best Practices doc and the demos eventually, but there are a lot of irons in the fire right now, so I at least wanted to get this out there for folks getting started.

Of course this doesn't have any impact on your existing apps if you don't refactor them to use this idiom. It's just a cleaner way of doing things.

-=Cliff>
« Last Edit: October 20, 2007, 11:37:25 by puremvc » Logged
Gradiation
Port to CSharp
Full Member
*
Posts: 41


View Profile Email
« Reply #1 on: January 05, 2008, 07:26:26 »

If this is now the recomended way of starting up an application, could we add a startup method to the IFacade interface? I prefer to hold the facade in an IFacade typed variable as apposed to a MyApplicationFacade typed variable.

What do you think?

Matt
« Last Edit: March 20, 2008, 12:04:08 by puremvc » Logged
starpause
Newbie
*
Posts: 2


View Profile Email
« Reply #2 on: April 17, 2008, 11:11:12 »

I have a question regarding what to pass when calling startup() on ApplicationFacade in an as3 project.

In Cliff's HelloFlash example, he is passing this.stage

:
package
{
import flash.display.MovieClip;
import org.puremvc.as3.demos.flash.helloflash.ApplicationFacade;

public class HelloFlash extends MovieClip
{
public function HelloFlash()
{
ApplicationFacade.getInstance().startup( this.stage );
}
}
}

however, in Lee's renju example he passes just this ...

:
package
{
import application.ApplicationFacade;
import flash.display.Sprite;

public class Main extends Sprite
{
private var facade:ApplicationFacade;

public function Main()
{
facade = ApplicationFacade.getInstance();
facade.sendNotification(ApplicationFacade.STARTUP, this);
}
}
}

i understand this will effect where children are attached (either to the stage with this.stage, or as siblings of the stage if you pass in this) but is either method preferable for any reasons?

thanks in advance for any insight or discussion  :)
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: April 19, 2008, 07:47:04 »

I believe it is the difference between MovieClip and Sprite. With a MovieClip you need to pass a reference to the this.stage object. With a Sprite, this will do.
Logged
jinglesthula
Newbie
*
Posts: 8


View Profile Email
« Reply #4 on: June 20, 2008, 12:53:12 »

Having issues with the facade starting up.

In my ApplicationFacade concrete facade class I have a method called startup, thus:

public function startup ( app:MyApp ):void {
   sendNotification ( STARTUP, app );
}

where STARTUP is public static const STARTUP:String = "startup"; in said class, and MyApp is the name of my main application (the mxml file in my src directory marked as the startup app for the project whose main mxml component is Application).

I've included the PureMVC swc in my library build path (it's in Flex Builder 3/PureMVC_AS3_2_0_3/bin).

In MyApp.mxml I have an import for the ApplicationFacade and I getInstance() and then call ApplicationFacadeInstance.startup.  For some reason the facade doesn't initialize properly and then the app continues running like normal (the view loads and I can click the buttons, etc.).

In my Application component I call a method (called starting) of MyApp on the creationComplete event.  In starting() I have the ApplicationFacadeInstance.startup() followed immediately by testingBool = true; (which variable I inspect later in the code to ensure that this particular block gets executed).  The problem is that if I call the startup method, the line testingBool = true; never executes.  If I comment out the startup method call, then testingBool = true; does execute.

I'm guessing it's some little thing I've missed after staring at the code too long.  Anybody have any ideas?

It occurs to me that since the libs folder in my project appears empty even though I set the library build path in the project properties that maybe I just need to put the swc in my project's lib folder directly rather than including the path.  However, I'd like to use the same swc in multiple projects.  But I'll give it a try just to check and see if that's the issue.  I kind of don't think it is, since I don't get compiler errors when I have my import statements, or at runtime when I instantiate the concrete facade.
« Last Edit: June 20, 2008, 03:24:56 by jinglesthula » Logged
jinglesthula
Newbie
*
Posts: 8


View Profile Email
« Reply #5 on: June 20, 2008, 03:31:45 »

Never you mind.  I found the problem.

Further into things, in a mediator's constructor I was sending the view component to the superclass constructor by using the getter name rather than the name that came in as an argument to the mediator class constructor, thus:

public class MyMediator extends Mediator implements IMediator {
...
public function MyMediator( viewComponent:MyComponent ) {
super ( NAME , myComponent );
}
private function get myComponent():MyComponent {
return viewComponent as MyComponent;
}
...
}

where my call to the superclass constructor should've been:

super ( NAME, viewComponent );

The wack thing is that it didn't throw a compiler error or a runtime error.  Apparently AS3 doesn't appreciate it if you use class getters in the superclass constructor.

Reminds me of the Dispair, Inc. poster that says something like "the purpose of your life may be to serve as a warning to others".  So, yes - don't try that in your own code.
Logged
Pages: [1]
Print