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: how to load my pureMVC adr_book.swf into a preloader.swf  (Read 9735 times)
malo
Newbie
*
Posts: 2


View Profile Email
« on: August 22, 2007, 04:27:11 »

Hi Cliff,

I've just accomplished my first working pureMVC test project. It just loads some address data from a mysql db into a datagrid using AMFPHP 1.9. It works just fine.

So far I have been using Aral Balkans ARP for my AS2 projects, but I think I'm definitely going to use your framework in the future.

Today I tried to use an external preloader to load my adr_book.swf but it generated this error in my flash cs3 output panel (tracing class contructors):

:
DataProxy constructed
StageMediator constructed
TypeError: Error #1009: Der Zugriff auf eine Eigenschaft oder eine Methode eines null-Objektverweises ist nicht möglich.
at com.malo.adr_book.view::StageMediator$iinit()
at com.malo.adr_book.controller::StartupCommand/execute()
at org.puremvc.core.controller::Controller/executeCommand()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at org.puremvc.patterns.observer::Observer/notifyObserver()
at org.puremvc.core.view::View/notifyObservers()
at org.puremvc.patterns.facade::Facade/notifyObservers()
at com.malo.adr_book::Adressbook$iinit()

What's the problem? I  used Colin Mooks loader example(Essential ActionScript 3.0, p.778) and made it the document class for preloader.fla

:
package
{
import flash.display.*;
import flash.net.URLRequest;
import flash.events.*;
import flash.text.*;

public class LoadAdressBook extends MovieClip
{

private var loader:Loader;// the asset loader
private var progressOutput:TextField;// textfield to display lad progress

// constructor
public function LoadAdressBook()
{

// create loader object and register for events
createLoader();

// create progress indicator
createProgressIndicator();

// start load operation
load(new URLRequest("adr_book.swf"));

}
private function createLoader()
{
// create the loader
loader = new Loader();

// register for events
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,progressListener);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeListener);
loader.contentLoaderInfo.addEventListener(Event.INIT,initListener);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,ioErrorListener);

}
private function createProgressIndicator():void
{
progressOutput = new TextField();
progressOutput.autoSize = TextFieldAutoSize.LEFT;
progressOutput.border = true;
progressOutput.background = true;
progressOutput.selectable = false;
progressOutput.text = "LOADING...";

}
private function load(urlRequest:URLRequest):void
{
// start load operation
loader.load(urlRequest);
// if progressOutput isn't already a descendant of this object ...
if (!contains(progressOutput))
{
// ... add it to display list
addChild(progressOutput);
}

}
private function progressListener(e:ProgressEvent):void
{
// update progress indicator. 1 kb is 1024 bytes, so divide by
// 1024 to convert output to kb
progressOutput.text = "LOADING: "
+ Math.floor(e.bytesLoaded / 1024)
+ "/" + Math.floor(e.bytesTotal /1024) + " KB";

}
private function initListener(e:Event):void
{
addChild(loader.content);

}
private function completeListener(e:Event):void
{
// remove progress indicator
removeChild(progressOutput);

}
private function ioErrorListener(e:IOErrorEvent):void
{
// evoked when a load error occurs
progressOutput.text = "LOAD ERROR";
}
}
}

This is the document class for my adr_book.fla ...

:
/**
* document class for adr_book project
*
* uses PureMVC framework
*/
package com.malo.adr_book
{
import flash.display.MovieClip;
import flash.display.Stage;
import com.malo.adr_book.ApplicationFacade;
import org.puremvc.patterns.observer.Notification;


public class Adressbook extends MovieClip
{

private var facade:ApplicationFacade;

public function Adressbook()
{
// Instantiate the ApplicationFacade
var facade:ApplicationFacade = ApplicationFacade.getInstance();

// Send the STARTUP notification
var note:Notification = new Notification( ApplicationFacade.STARTUP, this.stage);
facade.notifyObservers(note);

}

}
}

... here comes the ApplicationFacade.as

:
package com.malo.adr_book
{
    import org.puremvc.interfaces.IFacade;
    import org.puremvc.patterns.facade.Facade;
    import com.malo.adr_book.controller.*;
   
    public class ApplicationFacade extends Facade implements IFacade
    {
        // Notification name constants
        public static const STARTUP:String  = "startup";
public static const GET_ALL_CONTACTS:String = "get_all_contacts";
        public static const DATA_UPDATE:String  = "data_update";
public static const SHOW_INTRO_FORM:String  = "show_intro_form";
public static const SHOW_CONTACTS_FORM:String  = "show_contacts_form";

/**
         * Singleton ApplicationFacade Factory Method
         */
        public static function getInstance() : ApplicationFacade {
            if ( instance == null ) instance = new ApplicationFacade( );
            return instance as ApplicationFacade;
        }

        /**
         * Register Commands with the Controller
         */
        override protected function initializeController( ) : void
        {
            super.initializeController();           
            registerCommand( STARTUP, com.malo.adr_book.controller.StartupCommand );
registerCommand( GET_ALL_CONTACTS, com.malo.adr_book.controller.GetAllContactsCommand );
registerCommand( DATA_UPDATE, com.malo.adr_book.controller.DataUpdateCommand );
        }
       
    }
}

and finally the StartupCommand.as

:
package com.malo.adr_book.controller
{
import flash.display.Stage;
import org.puremvc.interfaces.ICommand;
import org.puremvc.interfaces.INotification;
import org.puremvc.patterns.command.SimpleCommand;

import com.malo.adr_book.ApplicationFacade;
import com.malo.adr_book.view.*;
import com.malo.adr_book.model.DataProxy;

public class StartupCommand extends SimpleCommand implements ICommand
{
/**
* Register the Proxies and Mediators.
*
* Get the View Components for the Mediators from the app,
* which passed a reference to itself on the notification.
*/
override public function execute( note:INotification ):void
{
facade.registerProxy(new DataProxy());

var stage:Stage = note.getBody() as Stage;
facade.registerMediator( new StageMediator( stage ) );

}
}
}

I apologize for all this code here. I'd rather uploaded my zipped example project, but it's 839 KB.

I hope this is sufficient info for anybody to help me with the preloader problem

greetings from bavaria

martin

Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: August 22, 2007, 05:30:46 »

Hi, Malo.

So, the swf runs by itself, just not when being loaded by a Loader?

From your stack trace, it appears everything has gone perfectly up until the actual StartupCommand's execute method.

In that method you instantiate and register your DataProxy. I have no reason to believe this is causing a problem in this circumstance.

I also see no reason why the loaded app should not be able to access the stage  in order to create and register the StageMediator.

So here are my thoughts for further investigation:

I think it could have to do with the LoaderContext or ApplicationDomain.

If your loading application is ALSO a PureMVC app, it's just possible that the default behavior for the Loader is getting in the way. It wants the loaded swf to be allowed to access the classes of the parent swf. If the loaded swf tries to define a class that's already been defined in the parent, then it is ignored. This may not be what you are wanting.

From the live doc:
# Child of loader's ApplicationDomain. The default. You can explicitly represent this choice with the syntax new ApplicationDomain(ApplicationDomain.currentDomain). This allows the loaded SWF file to use the parent's classes directly, for example by writing new MyClassDefinedInParent(). The parent, however, cannot use this syntax; if the parent wishes to use the child's classes, it must call ApplicationDomain.getDefinition() to retrieve them. The advantage of this choice is that, if the child defines a class with the same name as a class already defined by the parent, no error results; the child simply inherits the parent's definition of that class, and the child's conflicting definition goes unused unless either child or parent calls the ApplicationDomain.getDefinition() method to retrieve it.

http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/LoaderContext.html
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/ApplicationDomain.html

This is just a direction for your research. Please let me know what you find - if this is or isn't the answer.

-=Cliff>
Logged
sectore
Courseware Beta
Full Member
***
Posts: 29



View Profile WWW Email
« Reply #2 on: August 23, 2007, 12:18:50 »

Martin,

I've used an additional preloader-swf for a PureMVC project and it works like a charm.

But I've done the following steps:
- Adding the "extern" swf including my PureMVC app to the preloader swf after fired Event.COMPLETE (not on Event.INIT) to make sure loading all content
- Then I called an init function on my PureMVC app, which instantiates the ApplicationFacade and sends the "STARTUP" notification.

:
private function onAppComplete(event: Event):void
{
//
// opting out of compile time type checking
// therefore access external main class via event.target
var app:* = event.target.content;
//
// add content
this.addChild(app);
// init app
app.init();

removeAppLoaderListener();
}

I think you have to call the initialize process of your PureMVC app after loading all content and not within the constructor of your "extern" document class named "Adressbook".

-sectore
« Last Edit: August 23, 2007, 12:31:53 by sectore » Logged
malo
Newbie
*
Posts: 2


View Profile Email
« Reply #3 on: August 24, 2007, 02:25:44 »

@ Cliff
@ sectore

thanks a lot for your quick and helpful responses!

I got it working.

Both of your assumptions proofed to be true:

I think it could have to do with the LoaderContext or ApplicationDomain.
I think you have to call the initialize process of your PureMVC app after loading all content and not within the constructor of your "extern" document class named "Adressbook".


this is what my preloader class looks like now:

:
package
{
import flash.display.*;
import flash.net.URLRequest;
import flash.events.*;
import flash.text.*;
import fl.controls.Label;
import fl.controls.ProgressBar;
import fl.controls.ProgressBarMode;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;


public class Preloader extends MovieClip
{

private var loader:Loader;// the asset loader
private var progressOutput:Label;// label to display lad progress
private var myProgressBar:ProgressBar;// progressbar component

// constructor
public function Preloader()
{

// create loader object and register for events
createLoader();

// create progress indicator
createProgressIndicator();

// start load operation
load(new URLRequest("addressbook.swf"));

}
private function createLoader()
{
// create the loader
loader = new Loader();

// register for events
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,progressHandler);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler);
loader.contentLoaderInfo.addEventListener(Event.INIT,initHandler);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);



}
private function createProgressIndicator():void
{
progressOutput = new Label();
progressOutput.autoSize = TextFieldAutoSize.LEFT;
progressOutput.selectable = false;
progressOutput.text = "LOADING...";

// create myProgressBar
myProgressBar = new ProgressBar();
myProgressBar.height = 20;
myProgressBar.move(stage.stageWidth/2-myProgressBar.width/2,stage.stageHeight/2);
myProgressBar.mode = ProgressBarMode.MANUAL;

addChild(myProgressBar);
progressOutput.move(myProgressBar.x,myProgressBar.y - 20);

}
private function load(urlRequest:URLRequest):void
{
trace("Preloader::load()");

var loaderContext:LoaderContext = new LoaderContext();
loaderContext.applicationDomain = ApplicationDomain.currentDomain;

// start load operation
loader.load(urlRequest,loaderContext);

// if progressOutput isn't already a descendant of this object ...
if (!contains(progressOutput))
{
// ... add it to display list
addChild(progressOutput);

}

}
private function progressHandler(e:ProgressEvent):void
{
// update progress indicator. 1 kb is 1024 bytes, so divide by
// 1024 to convert output to kb
progressOutput.text = "LOADING: "
+ Math.floor(e.bytesLoaded / 1024)
+ "/" + Math.floor(e.bytesTotal /1024) + " KB";
myProgressBar.setProgress(e.bytesLoaded/1024,e.bytesTotal /1024);

}
private function initHandler(e:Event):void
{
trace("Preloader::initHandler()");

//addChild(loader.content);

}
private function completeHandler(e:Event):void
{

trace("Preloader::completeHandler()");

// remove progress indicator
removeChild(progressOutput);
// remove progressbar
removeChild(myProgressBar);

// opting out of compile time type checking
// therefore access external main class via event.target
var app:* = e.target.content;

// add content
addChild(app);
// init app
app.init();

//Adressbook(e.target.content).init(); // possible alternative for above




}
private function ioErrorHandler(e:IOErrorEvent):void
{
// evoked when a load error occurs
progressOutput.text = "LOAD ERROR";
}
}
}

... and here's the adapted document class of the loaded pureMVC project:

:
/**
* document class for address book project
*
* uses PureMVC framework
*/
package com.malo.addressbook
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.*;

import com.malo.addressbook.ApplicationFacade;
import org.puremvc.patterns.observer.Notification;

public class Addressbook extends MovieClip
{
private var facade:ApplicationFacade;

public function Addressbook()
{
trace("Addressbook constructed");

/**
* uncomment this for use without preloader.as
* ... and dont't forget to recompile adr_book.fla  ;-)
*/

// init();
}
// is called from preloader.as after Event.COMPLETE is fired
public function init()
{
trace("Addressbook::init()");
// Instantiate the ApplicationFacade
var facade:ApplicationFacade = ApplicationFacade.getInstance();

// Send the STARTUP notification
var note:Notification = new Notification( ApplicationFacade.STARTUP, this.stage);
facade.notifyObservers(note);

}
}
}

thanks again, guys

greetings

martin
Logged
Pages: [1]
Print