Category: PureMVC, XML, actionscript, as3, flash — joshspoon @ 9:44 pm —

Update at: How to Add and Remove Mediators in an Actionscript 3 PureMVC App

PureMVC imageSo I have been working alot w/ PureMVC, well everyday for the last month to be exact. I'm going to try to explain PureMVC the best way I know how. It may not be the best, but I hope it can get you started. And when you learn something let me know.

So the example I am doing is a simple one using Lee Brimelow's code from the ActionScript 3 Advanced XML example. The only difference between his and what I changed is some method name changes and putting it in PureMVC.

So if you don't know what PureMVC is or you are quite confused on how to use it...well so am I . I'm still learned and hopefully can teach some stuff. I'm not going to go into the specifics of this framework but think of it as a way to introduce a lot separation of code using the Model, View, Controller. I'll explain what I see as the benefits after I explain the example.

Look at lee's example:

Actionscript:
  1. var loader:URLLoader = new URLLoader();
  2. loader.addEventListener(Event.COMPLETE, onLoaded);
  3.  
  4. stage.addEventListener(MouseEvent.CLICK, changeColor);
  5.  
  6. var xml:XML;
  7. var kuler:Namespace = new Namespace("http://kuler.adobe.com/kuler/API/rss/");
  8. var ka:Array = new Array();
  9. var cc:int = 0;
  10.  
  11. function onLoaded(e:Event):void
  12. {
  13.  
  14. xml = new XML(e.target.data);
  15. var il:XMLList = xml.channel.item;
  16. for(var i:uint=0; i<il.length(); i++)
  17. {
  18. var sl:XML = il.kuler::themeItem.kuler::themeSwatches[i];
  19. var co:Object = new Object();
  20. co.c1 = sl.kuler::swatch.kuler::swatchHexColor.text()[0];
  21. co.c2 = sl.kuler::swatch.kuler::swatchHexColor.text()[1];
  22. co.c3 = sl.kuler::swatch.kuler::swatchHexColor.text()[2];
  23. co.c4 = sl.kuler::swatch.kuler::swatchHexColor.text()[3];
  24. co.c5 = sl.kuler::swatch.kuler::swatchHexColor.text()[4];
  25. ka.push(co);
  26. }
  27. drawColors(ka[0]);
  28. }
  29.  
  30. function drawColors(c:Object):void
  31. {
  32. graphics.beginFill(parseInt("0x" + c.c1));
  33. graphics.drawRect(0, 0, 200, 200);
  34. graphics.beginFill(parseInt("0x" + c.c2));
  35. graphics.drawRect(200, 0, 200, 200);
  36. graphics.beginFill(parseInt("0x" + c.c3));
  37. graphics.drawRect(400, 0, 200, 200);
  38. graphics.beginFill(parseInt("0x" + c.c4));
  39. graphics.drawRect(600, 0, 200, 200);
  40. graphics.beginFill(parseInt("0x" + c.c5));
  41. graphics.drawRect(800, 0, 200, 200);
  42. }
  43.  
  44. function changeColor(e:Event):void
  45. {
  46. if(cc == ka.length - 1)
  47. cc = 0;
  48. else
  49. cc++;
  50. drawColors(ka[cc]);
  51. }
  52.  
  53. loader.load(new URLRequest("http://kuler.adobe.com/kuler/API/rss/get.cfm?listtype=rating&itemsperpage=20"));

most everything but the drawColors() function are going into the dataProxy.
What's a dataProxy...hold on.

Make sure you download the swc or classes.

Here is what we are working with:

  1. PurelyKuler (Main Class)
    1. call the facade
    2. pass the DisplayObject to the app (a PureMVC method)
    Actionscript:
    1. package {
    2. import flash.display.Sprite;
    3. import flash.display.StageAlign;
    4. import flash.display.StageScaleMode;
    5.  
    6. //your main class file. you know that!
    7. public class PurelyKuler extends Sprite
    8. {
    9. public function PurelyKuler()
    10. {
    11. stage.align = StageAlign.TOP_LEFT;
    12. stage.scaleMode = StageScaleMode.NO_SCALE;
    13. //get facade instance
    14. var facade:PurelyKulerFacade = PurelyKulerFacade.getInstance();
    15. // make sprite that will be the viewcomponent to the mediator
    16. var colorContainer:Sprite = new Sprite();
    17. addChild(colorContainer);
    18. //start it up and pass the sprite to the app.
    19. facade.startup(colorContainer);
    20. }
    21. }
    22. }

  2. facade (PurelyKulerFacade)
    1. create singleton
    2. starts the app
    3. registers the command (StartUpCommand) I haven't explained that yet
    4. notify - PurelyKulerConstants.STARTUP and pass the DisplayObject
    Actionscript:
    1. package
    2. {
    3. import com.joshspoon.etc.purelyKuler.PurelyKulerConstants;
    4. import com.joshspoon.etc.purelyKuler.controller.*;
    5.  
    6. import org.puremvc.interfaces.IFacade;
    7. import org.puremvc.patterns.facade.Facade;
    8. import org.puremvc.patterns.observer.Notification;
    9.  
    10. public class PurelyKulerFacade extends Facade implements IFacade
    11. {
    12. // Singleton Method
    13. public static function getInstance(): PurelyKulerFacade {
    14. if (instance == null) {
    15. instance = new PurelyKulerFacade( );
    16. }
    17. return instance as PurelyKulerFacade;
    18. }
    19.  
    20. // Broadcast the STARTUP Notification
    21. public function startup(app:Object):void {
    22.  
    23. notifyObservers(new Notification(PurelyKulerConstants.STARTUP, app));
    24. }
    25.  
    26. // Register Commands with the Controller
    27. // like EVENT this is listening for STARTUP to excute the StartUpCommand
    28. override protected function initializeController():void {
    29. super.initializeController();
    30. registerCommand(PurelyKulerConstants.STARTUP, StartUpCommand);
    31. }
    32.  
    33. }
    34. }

  3. SimpleCommand (StartUpCommand) - similar to your event handler
    1. registerProxy (KulerDataProxy) not spoke about yet
    2. registerMediator(PurelyKulerMediator) - not spoken of yet
    Actionscript:
    1. package com.joshspoon.etc.purelyKuler.controller
    2. {
    3. import com.joshspoon.etc.purelyKuler.model.KulerDataProxy;
    4. import com.joshspoon.etc.purelyKuler.view.PurelyKulerMediator;
    5.  
    6. import flash.display.*;
    7.  
    8. import org.puremvc.interfaces.ICommand;
    9. import org.puremvc.interfaces.INotification;
    10. import org.puremvc.patterns.command.SimpleCommand;
    11.  
    12. public class StartUpCommand extends SimpleCommand implements ICommand
    13. {
    14. override public function execute(notification:INotification):void
    15. {
    16. // Create and register proxy
    17.  
    18. facade.registerProxy(new KulerDataProxy());
    19.  
    20. // Create and register the mediator, colorContainer passed as the viewcomponent of the Mediator
    21.  
    22. facade.registerMediator(new PurelyKulerMediator(notification.getBody() as Sprite));
    23.  
    24. }
    25.  
    26. }
    27. }

  4. Proxy (KulerDataProxy) - connects to databases/REST/and the like
    1. setup connection for xml
    2. expose a loadInfo method for request of data
    3. onKulerLoad method just like lee's except it notifies DATA_LOADED and passes the array of colors
    Actionscript:
    1. package com.joshspoon.etc.purelyKuler.model
    2. {
    3. import com.joshspoon.etc.purelyKuler.PurelyKulerConstants;
    4.  
    5. import flash.events.Event;
    6. import flash.net.*;
    7.  
    8. import org.puremvc.interfaces.IProxy;
    9. import org.puremvc.patterns.observer.Notification;
    10. import org.puremvc.patterns.proxy.Proxy;
    11.  
    12. public class KulerDataProxy extends Proxy implements IProxy
    13. {
    14.  
    15. public static const NAME:String = "KulerDataProxy";
    16. private var _loader:URLLoader;
    17. private var _xml:XML;
    18. private var kuler:Namespace;
    19. private var _ka:Array;
    20.  
    21. public function KulerDataProxy( data:Object = null )
    22. {
    23. super ( NAME, data );
    24.  
    25. setupNetwork();
    26. trace(NAME + " ready");
    27. }
    28. // has everything to prepare the data request to Kuler.
    29. private function setupNetwork():void
    30. {
    31. kuler     = new Namespace("http://kuler.adobe.com/kuler/API/rss/");
    32. _ka     = new Array();
    33. _loader = new URLLoader();
    34. _loader.addEventListener(Event.COMPLETE, onKulerLoad);
    35.  
    36. }
    37.  
    38. // function called to start action of dataProxy
    39. public function loadInfo():void
    40. {
    41. _loader.load(new URLRequest("http://kuler.adobe.com/kuler/API/rss/get.cfm?listtype=rating&itemsperpage=20"));
    42. }
    43. // this is an overriden inherited function from PureMVC
    44. override public function getProxyName():String
    45. {
    46. return NAME;
    47. }
    48.  
    49. //when data is loaded
    50. private function onKulerLoad(e:Event):void
    51. {
    52. //for more info see: http://www.gotoandlearn.com/player.php?id=65
    53. _xml = new XML(e.target.data);
    54. var il:XMLList = _xml.channel.item;
    55. for(var i:uint=0; i<il.length(); i++)
    56. {
    57. var sl:XML = il.kuler::themeItem.kuler::themeSwatches[i];
    58. var co:Object = new Object();
    59. co.c1 = sl.kuler::swatch.kuler::swatchHexColor.text()[0];
    60. co.c2 = sl.kuler::swatch.kuler::swatchHexColor.text()[1];
    61. co.c3 = sl.kuler::swatch.kuler::swatchHexColor.text()[2];
    62. co.c4 = sl.kuler::swatch.kuler::swatchHexColor.text()[3];
    63. co.c5 = sl.kuler::swatch.kuler::swatchHexColor.text()[4];
    64. _ka.push(co);
    65.  
    66. }
    67. trace("co.c1: " + _ka[0].c1);
    68.  
    69. //once all the color data is pushed in to the array
    70. //send notifications
    71. facade.notifyObservers(new Notification(PurelyKulerConstants.DATA_LOADED, _ka));
    72. }
    73.  
    74. }
    75. }

  5. Mediator (PurelyKulerMediator) -the view of the application
    1. create loading textField and add it to viewComponent(colorComponent)
    2. when data returns allow click
    3. draw colors.
    Actionscript:
    1. // code created by Lee Brimelow http://www.gotoandlearn.com/player.php?id=65
    2. // modified by Josh Weatherspoon: http://etc.joshspoon.com/wp-content/uploads/2008/02/purelykuler_puremvc_example.zip
    3. package com.joshspoon.etc.purelyKuler.view
    4. {
    5. import com.joshspoon.etc.purelyKuler.PurelyKulerConstants;
    6. import com.joshspoon.etc.purelyKuler.model.KulerDataProxy;
    7.  
    8. import flash.display.*;
    9. import flash.events.*;
    10. import flash.text.*;
    11.  
    12. import org.puremvc.interfaces.IMediator;
    13. import org.puremvc.interfaces.INotification;
    14. import org.puremvc.patterns.mediator.Mediator;
    15.  
    16. public class PurelyKulerMediator extends Mediator implements IMediator
    17. {
    18. public static const NAME:String = "PurelyKulerMediator";
    19. private var _tf:TextField; // will display loading...
    20. private var _ka:Array = []; //array to hold color data from the Proxy
    21. private var cc:int = 0; // index in th _ka array
    22.  
    23. public function PurelyKulerMediator(viewComponent:Object=null)
    24. {
    25. _tf = new TextField();
    26.  
    27. super(viewComponent);// the colorContainer
    28. DisplayObjectContainer(viewComponent).addChild(_tf);
    29. loading();
    30. trace(NAME + " started");
    31. }
    32. // a PureMVC override
    33. override public function getMediatorName():String
    34. {
    35. return NAME;// passes name to access this in the app
    36. }
    37. // a PureMVC override
    38. override public function getViewComponent():Object
    39. {
    40. return viewComponent;
    41. }
    42. // what this mediator is listening for
    43. override public function listNotificationInterests():Array
    44. {
    45. return [PurelyKulerConstants.DATA_LOADED]
    46. }
    47.  
    48. override public function handleNotification(notification:INotification):void
    49. {
    50. switch (notification.getName())// like Event.CHANGE
    51. {
    52. case PurelyKulerConstants.DATA_LOADED:
    53. _ka = (notification.getBody() as Array) // like evt.data
    54. changeColor();
    55. DisplayObjectContainer(viewComponent).addEventListener(MouseEvent.CLICK, changeColor, false, 0, true); //real events should only be in mediator and call change through notifications
    56. break;
    57. }
    58. }
    59. // calling the load method for the xml in teh proxy
    60. private function loading():void
    61. {
    62. _tf.text = "Loading...";
    63. KulerDataProxy(facade.retrieveProxy(KulerDataProxy.NAME)).loadInfo();
    64. }
    65. //see lee's example
    66. private function changeColor(e:MouseEvent = null):void
    67. {
    68. if(cc == _ka.length - 1)
    69. cc = 0;
    70. else
    71. cc++;
    72. drawColors(_ka[cc]);
    73. }
    74. //see lee's example
    75. private function drawColors(c:Object):void
    76. {
    77. _tf.text = "";
    78. viewComponent.graphics.clear();
    79. viewComponent.graphics.beginFill(parseInt("0x" + c.c1));
    80. viewComponent.graphics.drawRect(0, 0, 200, 200);
    81. viewComponent.graphics.beginFill(parseInt("0x" + c.c2));
    82. viewComponent.graphics.drawRect(200, 0, 200, 200);
    83. viewComponent.graphics.beginFill(parseInt("0x" + c.c3));
    84. viewComponent.graphics.drawRect(400, 0, 200, 200);
    85. viewComponent.graphics.beginFill(parseInt("0x" + c.c4));
    86. viewComponent.graphics.drawRect(600, 0, 200, 200);
    87. viewComponent.graphics.beginFill(parseInt("0x" + c.c5));
    88. viewComponent.graphics.drawRect(800, 0, 200, 200);
    89. }
    90. }
    91. }

  6. Lastly the constants I use in PurelyKulerConstants
Actionscript:
  1. package com.joshspoon.etc.purelyKuler
  2. {
  3. // a little excess for this example but I like having a global place to store contants
  4. public class PurelyKulerConstants
  5. {
  6. public static const DATA_LOADED:String     = "DataLoaded";
  7. public static const STARTUP:String         = "Startup";
  8. }
  9. }

You can expand this and make another proxy or mediator and plug and play pieces, since you code is not tightly coupled. That is what I see as benefit.

That should be it. I hope that helps

Enjoy!

source

Horaayy..there are 3 comment(s) for me so far ;)

#1

I've found tutorials on puremvc extremely thin on the ground so thanks for sharing this, will have a play when I get home from work.

On first impressions it seems to be a lot of overhead code, I know this is a small example and with a larger project the overhead code wont seem as large but the original 53 line example jumps to 258 lines!

On a side note, how do you find the framework? I really need to get in to a framework for as3 apps!

Cheers

Anton Mills wrote on August 13, 2008 - 10:59 am
#2

Yeah this is just an example. You'd never use PureMVC for a project this small.

you can find PureMVC at http://www.puremvc.org/

joshspoon wrote on August 14, 2008 - 2:37 pm
#3

I think he meant what do you think of it? (how do you find the framework?)
I get this: '1118: Implicit coercion of a value with static type Object to a possibly unrelated type String.

ralph wrote on November 11, 2008 - 8:47 am
You can leave a response, or trackback from your own site.

Write Your Comment

Comment Guidelines: Basic XHTML is allowed (a href, strong, em, code). All line breaks and paragraphs will be generated automatically.

You should have a name, right? 
Your email address, I promised I won't tell it to anyone. 
If you have a web site or blog, you can type the URL right here. 
This is where you type your comments. 
Remember my information for the next time I visit.
 

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word