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 [2]
Print
Author Topic: Flex Mobile ViewNavigator and PureMVC  (Read 57006 times)
shredding
Newbie
*
Posts: 6


View Profile Email
« Reply #15 on: June 14, 2011, 11:55:15 »

... after reviewing my upper post, I saw, that I broke my own approach  ::)

The LocalStorageProxy does not report to the ApplicationProxy, thus the LocalStorage is coupled to the ApplicationMediator. I'll fix that :)
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #16 on: June 14, 2011, 04:42:02 »

Someone gave me the interesting opinion, that the Mediator are upstreamed Controllers
Wrong. This leads to the idea that they should house logic. That is not the purpose of a Mediator at all. It's role is to mediate, that's why it's called a Mediator. It mediates communication between a view component and the rest of the application. Commands house logic, you should really move all the logic out of the Mediator and into a command, triggered in the way I showed previously by just sending off a note.

Sure, you can do logic in the mediator, but that overloads it with responsibilities. You end up with these huge bloated Mediators when you keep finding logic to stuff in there for different things. Keep the mediator's role simple and each command's work simple. All your classes should end up being as simple as possible. You're not striving for the fewest possible number of classes, you're striving for a system of clear roles, responsibilities and collaborations.

Also, your view should not know your mediator, even in order to know its NAME. We're also striving for loose-coupling. The view component is more portable if it doesn't know anything about its mediator. If the view has to import the mediator in order to give itself an id, then you're tightly-coupled. That component cannot be used without the mediator. In a properly written system you could take all the view components and use them with another framework, without having to take any of the PureMVC code along. (Why you'd be migrating away from PureMVC is a mystery, but you could do it. That's portability).

With this code:
:
if(activeView!=null) {
this.facade.removeMediator(activeView.id + 'Mediator');
}
         
why do you want to re-mediate the view component? if it is already mediated then there's no need to remove the mediator and then register it again.

-=Cliff>
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #17 on: June 14, 2011, 04:48:42 »

The LocalStorageProxy does not report to the ApplicationProxy, thus the LocalStorage is coupled to the ApplicationMediator. I'll fix that

Actually it's fine for any mediator to know any proxy, just not the other way round. Here again, the direction of the coupling is key. If anything's truly reusable in your app it'll be the Model region; the proxies.

Thus the Proxy should know absolutely nothing about the rest of the app (no imports from the View or Controller regions). On the other hand, the View region has no reason in life but to present the data from the Model and allow the user to interact with it. Therefore, it is understandable that the Mediators will have some intimate knowledge about the shape of the domain model, and the Proxies that allow interaction with it.

So for simply taking data from the view in response to an event and passing it to a method on a proxy for dispatch to the server, or for telling a proxy to load a certain selected piece of data, the mediator may retrieve and interact directly with the Proxy. Coupling in that direction (view to model) is fine.

-=Cliff>
Logged
shredding
Newbie
*
Posts: 6


View Profile Email
« Reply #18 on: June 16, 2011, 12:39:02 »

Thank you so much for your detailed explaination. I've adjusted my Code.

But I do not understand, why this is a better approach then mine "all proxies report to a major proxy":


Actually it's fine for any mediator to know any proxy, just not the other way round. Here again, the direction of the coupling is key. If anything's truly reusable in your app it'll be the Model region; the proxies.



In my Examlpe I use a LocalStorageProxy. If in the future, the Datasource would change to an XML, I'd have to adjust the Mediator. If the LocalStorageProxy would process its data and pushes it to an ApplicationProxyVO, no one would have to care (the decoupling would work in both directions). Would you mind to drop a line bout this? Thanks!
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #19 on: June 17, 2011, 09:20:24 »

But I do not understand, why this is a better approach then mine "all proxies report to a major proxy":
You can certainly build a hierarchy of Proxies, it's just that you're likely to end up with a massive Proxy at the top that is acting more like a delegate really. And a domain model that's not easy to reuse in different apps.

By having the parts of the Mediators and Commands that need to interact with the domain mode simply talk directly to the Proxies they need to, you're more likely to be able to reuse just the parts parts of the domain model you need in another program.

For instance, it is increasingly likely that you may have web, mobile, desktop and tablet versions of your application. You might not be planning them from the start, but when it does, you'll probably find yourself using subsets of the whole model package in each application. You may use certain Proxies only with the desktop and mobile apps, where you can enable an offline cache for resources that have to be pulled down over the web every time in the web or mobile apps. And all the different apps will likely have a different set of use-cases that take into account the unique form-factor and limitations of each.

That said, there is one area I've put a hierarchy of Proxies to good use; using the PureMVC/AIR XMLDatabase Utility. It is basically an abstract Proxy that can read, write and create a default XML structure on disc for a particular purpose. Rather than write a bunch of different XML files for different data that an app stores, the XMLDatabase utility lets you roll them all up into one XML file, then when it loads the file, you can override a method and take the loaded XML and 'snap off twigs' of it and feed other Proxies that tend just their twig. For instance in my PantryMouse demo application I have Items, Stores, Trips and Lists as separate elements in the XML that are managed by different Proxies. They all are really maintaining the same big structure, which gets written out periodically and when you exit the app. But the rest of the application talks to the sub-proxies, not to the main proxy.

In my Examlpe I use a LocalStorageProxy. If in the future, the Datasource would change to an XML, I'd have to adjust the Mediator.
The place to shield your view from major changes in data format is by creating value objects. And if you decide to use XML, you can always wrap it in a vo with typed, implicit getters and setters. I call this the SmartVO1.

-=Cliff>

1See an example of a 'Smart VO' here: http://forums.puremvc.org/index.php?topic=1293.msg5973#msg5973
Logged
dries
Newbie
*
Posts: 2


View Profile Email
« Reply #20 on: November 24, 2011, 05:46:25 »

I'm setting up a mobile flex iOS application with ViewNavigators. I'm used to the pureMVC framework, but i'm still not sure how to use it in combination with those ViewNavigators.

The views in the ViewNavigators are created/removed during the run of an application. This minimizes the used memory of the application. Memory use should be low since an iOS application keeps on running in the background if you exit the application. So i don't want to use the approach to create all view at startup and keep them in memory.

Did a small test, and it seems that views are not reused: each time a view is needed, a new instance is created. This means that mediators should be created and removed whenever a view is created/removed.

Is there a good way to do this?

Can the id be used to look what mediator should be created? In this case: how can we specify an id for the 'firstView' that will be created?

Or should we look at the class type of the view? I suppose this means views can not be reused within an application..
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #21 on: November 26, 2011, 05:43:59 »

I have recently run into this problem myself in a project I'm working on for the iPad. In my spare time, I'm just putting the finishing touches on my new O'Reilly PureMVC book, or I'd already have a demo out showing how to handle this scenario. I'd thought I'd include it in the book, but ruled it out for lack of time. But because this is a really important issue, I'll elaborate here, then refine this post into a section in the Advanced View Topics chapter of the book. My final draft goes in Monday, so thanks for bringing up this issue today!

Flex Mobile presents a radically different paradigm in the way the view is constructed (and destroyed), so the previous approaches to mediation don't really fit. But fear not, PureMVC is adaptable.

Flex Web or Desktop Mediation Strategy
Normally, in a Flex browser or desktop app, you'd have an Application or WindowedApplication declaring an initial hierarchy, which you mediate once it is created. When you want to add a view component to an Application or WindowedApplication you do an addChild() to add it.

Handle the app's applicationComplete event by passing a reference to the application into your ApplicationFacade.startup() method, where you send it off in a notification to a StartupCommand where you mediate the application and any other top-level components on the display list that need mediation.

Mediators can further mediate the top level children of their view components. If view components have their creation deferred (e.g., children of a ViewStack not being created until navigated to), then your mediator should listen for Event.ADDED or FlexEvent.CREATION_COMPLETE events from the view component and mediate them in the event handler.

And at any time, you might want to dynamically create a component and add it to the display list with mediation. You just create it, register a mediator for it, and send it off in a notification that is responded to by an ApplicationMediator, who takes the component from the note and adds it as a child of the application.

Mediators are usually long-lived in a web or desktop app, as view components are rarely destroyed. except when View States are employed, but that's another story (more like Flex Mobile Views actually).

Flex Mobile Mediation Strategy
The ViewNavigator is essentially a stack that Views are pushed onto or popped off. A ViewNavigatorApplication is a top-level application for mobile that uses a ViewNavigator as the primary container.

A major difference from Application or WindowedApplication is you don't create a View before pushing it onto the ViewNavigator, you actually pass in the class name and it creates it for you. So, that means you can't use the PureMVC idiom of creating a component, mediating it, and then sending it off in a notification to be added to the Stage.

You can have a 'firstView', which it will create automatically at startup, and you may mediate that at startup. Other Views are only created when pushed onto the ViewNavigator or popped back to. All Views are destroyed when they are popped off the ViewNavigator, or when another View is popped onto the ViewNavigator on top of them, except...

There is a destructionPolicy="never" attribute that you can declare on a View. However, this only means it stays in memory when something is pushed onto the ViewNavigator in front of it. But when you pop a View with destructionPolicy="never", it is actually destroyed. So "never" really means "never destroy this View when something is pushed on top of it".

When you push a View onto the ViewNavigator, you can also supply an arbitrary Object as data to be passed to the View when it is created.

And a ViewNavigator has a property called 'context' which is an arbitrary Object. You can use this to keep track of what you're doing. I used it as a constant that told me what View I was on without referring to the active View and checking its type.

In Flex Mobile, you need to dynamically mediate your Views which are created and destroyed all the time. Your mediators only live as long as the component they mediate. You also need to manage when you push a View onto the ViewNavigator, and when you pop back to one. Finally, you need to consider which Views are important to set destructionPolicy="never" on.

Hypothetical Flex Mobile App
Let's consider an application where you can log in, view a list of your things, maintain your things, or see an screen with info like what version of the app you are running, how much free space your mobile device has, and how much space your things are currently taking up.

You have a LoginView as your first View. Once logged in, you move to a ListView, where you can see a list of your 'things'. From there, you can either log out (going back to the LoginView), view info about the app in an InfoView, or edit one of your 'things' in the FormView.

Your ListView might take awhile to render, especially once you have a lot of 'things'. So you'll want to set destructionPolicy="never" on it so that it doesn't get destroyed when you push an InfoView or FormView on top of it. But remember when you log out, the ListView will be popped off the stack and will be destroyed. Which makes sense because if you log in as someone else you don't want the previous list in memory anyway. Also, the InfoView will take an InfoVO

So, this all begins with the application itself. It needs to expose some methods for showing different Views. It will encapsulate all the push/pop logic, so the mediator doesn't need to know any thing other than what method to call to show a given View. Also, we want to mediate the initial LoginView component, so we need a method for getting the active View from the application.

Here are the important actors and their roles, in order of appearance in the startup process:

  • The IMyMobileApp Interface - An interface showing the methods the methods this hypothetical application should implement
  • The MyMobileApp Application - Based on ViewNavigatorApplication, starts up PureMVC, and implements the IMyMobileApp Interface
  • The Application Facade - Based on Facade, implements getInstance() and startup() methods
  • The Startup Command - Prepare the Controller, Model, and View in that order
  • The Application Mediator - Listen to the application for Event.ADDED, sending any Views off in a MEDIATE_VIEW Notification, listen for Notifications to change Views, calling the appropriate methods on the app in response, and mediate the firstView
  • The Mediate View Command - Create and register the appropriate Mediator for the View, removing any existing instance first
  • The List View - A typical View, except it needs destructionPolicy="never"

Now some code:


The IMyMobileApp Interface
:
package com.me.myapp.view
{
import com.me.myapp.model.vo.InfoVO;

import flash.events.IEventDispatcher;

import spark.components.View;

public interface IMyMobileApp extends IEventDispatcher
{
function getActiveView():View;
function showLoginView():void;
function showListView():void;
function showInfoView( infoVO:InfoVO ):void;
function showFormView():void;
}
}

The MyMobileApp Application
:
<?xml version="1.0" encoding="utf-8"?>
<!-- FLEX MOBILE APPLICATION-->
<s:ViewNavigatorApplication
firstView="com.me.myapp.view.component.LoginView"
implements="com.me.myapp.view.IMyMobileApp"
applicationComplete="facade.startup(this)"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fx="http://ns.adobe.com/mxml/2009">


<fx:Script>
<![CDATA[
import com.me.myapp.ApplicationFacade;
import com.me.myapp.model.vo.InfoVO;
import com.me.myapp.view.component.InfoView;
import com.me.myapp.view.component.ListView;
import com.me.myapp.view.component.LoginView;
import com.me.myapp.view.component.FormView;

import spark.components.View;

private var facade:ApplicationFacade = ApplicationFacade.getInstance();

public static const LOGIN:String  = "LoginView";
public static const LIST:String    = "ListView";
public static const FORM:String  = "FormView";
public static const INFO:String   = "InfoView";

// Read-only context
private function get context():String
{
// if there is no context, then we are on the LoginView,
// set by firstView (we can't set a context for firstView)
return (navigator.context)?String(navigator.context):LOGIN;                  
}

//--------------------------------------------------------------------------
// Below methods satisfy IMyMobileApp interface
//--------------------------------------------------------------------------

// GET THE ACTIVE VIEW
public function getActiveView():View
{
// Since the LoginView is specified as the 'firstView'
// we need to mediate it in the traditional way, which means
// we need a way to get the active view from the mediator
return navigator.activeView;                  
}

// SHOW THE LOGIN VIEW
public function showLoginView( ):void
{
// Only return to LoginView if we're not already on it
if ( context != LOGIN ) navigator.popToFirstView();
}

// SHOW THE LIST VIEW
public function showListView( ):void
{
// Only act if we're not already on the ListView
if ( context != LIST )
{
// If returning (from Info or Form views), just pop
// otherwise push a new ListView
var returning:Boolean = ( context == INFO || context == FORM );
if ( returning ) {
navigator.popView();
} else {
navigator.pushView( ListView,  null, LIST );
}
}
}

// SHOW THE FORM VIEW
public function showFormView(  ):void
{
// Only push a FormView if we're not already on it
if ( context != FORM )
navigator.pushView( FormView, null, FORM );
}

// SHOW THE INFO VIEW (PASSING IN INFO VO)
public function showInfoView( infoVO:InfoVO ):void
{
// Only push an InfoView if we're not already on it
// Pass in the InfoVO from the note body
if ( context != INFO )
navigator.pushView( InfoView, infoVO, INFO );                  
}


]]>
</fx:Script>

</s:ViewNavigatorApplication>

The Application Facade
:
package com.me.myapp
{
import com.me.myapp.controller.command.StartupCommand;
import com.me.myapp.controller.constants.AppConstants;
import com.me.myapp.view.IMyMobileApp;

public class ApplicationFacade
{

public static function getInstance() : ApplicationFacade
{
if ( instance == null ) {
instance = new ApplicationFacade();
}
return ApplicationFacade( instance );
}

public function startup( app:IMyMobileApp ):void
{
registerCommand( AppConstants.STARTUP, StartupCommand );
sendNotification( ViewerConstants.STARTUP, app );
}
}
}

The Startup Command
:
package com.me.myapp.controller.command
{
v import com.me.myapp.model.proxy.InfoProxy;
import com.me.myapp.model.proxy.ThingProxy;
import com.me.myapp.view.IMyMobileApp;
import com.me.myapp.view.mediator.ApplicationMediator;

import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.command.SimpleCommand;

public class StartupCommand extends SimpleCommand
{
override public function execute( note : INotification ) : void
{
// Prepare the Controller
facade.registerCommand( AppConstants.MEDIATE_VIEW, MediateViewCommand );            
// Prepare the Model
facade.registerProxy( new ThingProxy( ) );
facade.registerProxy( new InfoProxy( ) );

// Prepare the View
var app:IMyMobileApp = IMobileViewer( note.getBody() );
facade.registerMediator( new ApplicationMediator( app ) );
}
}
}


The Application Mediator
:
package com.me.myapp.view.mediator
{
import com.me.myapp.controller.constants.AppConstants;
import com.me.myapp.view.IMyMobileApp;
import com.me.myapp.model.InfoVO;

import flash.events.Event;

import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.mediator.Mediator;

import spark.components.View;

public class ApplicationMediator extends Mediator
{
public static const NAME:String = "ApplicationMediator";

// CONSTRUCTOR - HANDLE COMPONENT BY ITS INTERFACE
public function ApplicationMediator( app:IMyMobileApp )
{
super( NAME, app );
}

// CALLED AT REGISTRATION - LIST NOTIFICATION INTERESTS
override public function listNotificationInterests():Array
{
return [ AppConstants.SHOW_LOGIN,
AppConstants.SHOW_LIST,
AppConstants.SHOW_FORM,
AppConstants.SHOW_INFO,
      ];
}

// CALLED AT REGISTRATION - LISTEN FOR EVENTS, MEDIATE FIRST VIEW
override public function onRegister():void
{
// Listen for Views to be added to the ViewNavigatorApplication
app.addEventListener( Event.ADDED, handleAddedEvent );

            
// Mediate the firstView (currently the LoginView)
sendNotification( AppConstants.MEDIATE_VIEW, app.getActiveView() );
}

// HANDLE NOTIFICATIONS TO CHANGE VIEWS
override public function handleNotification( note:INotification ):void
{
switch ( note.getName() )
{
case AppConstants.SHOW_LOGIN:
app.showLoginView();
break;

case AppConstants.SHOW_LIST:
app.showListView();
break;

case AppConstants.SHOW_FORM:
app.showFormView();
break;

case AppConstants.SHOW_INFO:
app.showInfoView( InfoVO( note.getBody() ) );
break;
}
}

// HANDLE ADDED EVENTS (Event.ADDED)
private function handleAddedEvent( event:Event ):void
{
if ( event.target is View ) {
sendNotification( AppConstants.MEDIATE_VIEW, event.target );
}
}
        
  // CAST THE VIEW COMPONENT TO THE PROPER TYPE
private function get app():IMyMobileApp
{
return viewComponent as IMyMobileApp;
}
}
}


The Mediate View Command
:
package com.me.myapp.controller.command
{
import com.me.myapp.view.component.InfoView;
import com.me.myapp.view.component.ListView;
import com.me.myapp.view.component.LoginView;
import com.me.myapp.view.component.FormView;
import com.me.myapp.view.mediator.InfoViewMediator;
import com.me.myapp.view.mediator.ListViewMediator;
import com.me.myapp.view.mediator.LoginViewMediator;
import com.me.myapp.view.mediator.FormViewMediator;

import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.interfaces.IMediator;
import org.puremvc.as3.patterns.command.SimpleCommand;

import spark.components.View;

public class MediateViewCommand extends SimpleCommand
{
/**
* Each View is destroyed once it is moved away from,
* thus Mediators must also be transient. Any existing
* Mediator is removed, and a new one registered
* along with the new View. Any additional mediators
* associated with the children of these Views should be
* registered and removed the onRegister() and onRemove()
* methods of the View's Mediator.
*/
override public function execute( note:INotification ):void
{
var view:View = View( note.getBody() );
var mediator:IMediator;
switch ( view.className )
{
case "LoginView":
facade.removeMediator( LoginViewMediator.NAME );
mediator = new LoginViewMediator( view as LoginView );
break;

case "ListView":
facade.removeMediator( ListViewMediator.NAME );
mediator = new ListViewMediator( view as ListView );
break;

case "FormView":
facade.removeMediator( FormViewMediator.NAME );
mediator = new FormViewMediator( view as FormView );
break;

case "InfoView":
facade.removeMediator( InfoViewMediator.NAME );
fmediator = new InfoViewMediator( view as InfoView );
break;
}
if (mediator) facade.registerMediator( mediator );
}
}
}

The List View
:
<?xml version="1.0" encoding="utf-8"?>
<!-- LIST VIEW -->
<s:View xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fx="http://ns.adobe.com/mxml/2009"
destructionPolicy="never">


<!-- LIST STUFF HAPPENS HERE -->

</s:View>
« Last Edit: November 26, 2011, 07:51:15 by puremvc » Logged
dries
Newbie
*
Posts: 2


View Profile Email
« Reply #22 on: November 28, 2011, 09:15:45 »

thx for the detailed explanation.

Had some time to experiment a bit and came to more or less the same solution. I'll try to highlight the things i did different:

Remove mediators

Remove mediators when a view is removed. My thought why this is important: If you keep the mediator, you keep a reference to the view. So the view can never be garbage collected until the mediator is also removed.

In your solution, you keep the current mediator until the next time a view of the same Class is created. This implies that once your application has visited all views, you use the same amount of memory as creating all views on startup and keep a fixed reference to them.

No centralized registration of mediators

I'm registering my mediators by listening to the ElementExistenceEvent.ELEMENT_ADD events of the viewNavigator and TabbedViewNavigator.

I'm removing my mediators by listening to the ElementExistenceEvent.ELEMENT_REMOVE events.

This way, you can reuse the same View Class in for example two different ViewNavigators in one TabbedViewNavigator.

Example: You have an application with a View that can represent a list of persons: PersonListView. In one Tab you display family in a family viewNavigator, in a second tab you display friends in a friends viewNavigator, .. By splitting the registration of the mediators, you can reuse the same View: When a PersonListView view is created in the family viewNavigator, you create a family mediator which populates the view with family data. When the a PersonListView is created in the friends viewNavigator, your create a friend mediator which populates the view with friends data.

When you register your mediators in one centralized command, you can not know with what data that view should be populated.. or is there an other way to do this? If you could do this in any other way, i would prefer the centralized solution.. I don't think you can use the id property, cause there is no way to set it when you call the navigator.pushView(View) method...

EDIT: Just noticed that the third parameter of the pushView method,  'context' can be used in order to reuse view components. Going for the centralized approach..
« Last Edit: November 28, 2011, 09:22:42 by dries » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #23 on: November 28, 2011, 10:31:01 »

Remove mediators when a view is removed.
A good optimization, certainly. You can have the Mediator itself listen to the View for Event.REMOVED, call facade.removeMediator(this.getMediatorName()) in response.
Logged
purenewb
Newbie
*
Posts: 2


View Profile Email
« Reply #24 on: December 13, 2011, 03:41:58 »

I am just getting started with PureMVC and I have used it with a Flash project written in Flash Builder with great results. I would like to use the framework on a Flex Mobile application that I am building, but I can't figure out how to adapt it to the TabbedViewNavigatorApplication. I tried listening to ElementExistenceEvents as pointed out above, but I cannot receive the events on the application root or tabbedNavigator, etc.

Does someone have a clearer real world example outlining how to build a tabbed mobile app with PureMVC?

Thank you!
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #25 on: December 13, 2011, 04:34:15 »

I tried ElementExistenceEvent and had difficulties as well. But there are lots of life cycle events that you could listen for, or you could have your Views dispatch a bubbling custom event on creationComplete of the View in question.

Actually if you look at my ViewNavigatorApplication example a couple of replies back, you'll see I'm listening for Event.ADDED and then mediating if the target of the event is a View.


In the ApplicationMediator
In onRegister():
:
// CALLED AT REGISTRATION - LISTEN FOR EVENTS, MEDIATE FIRST VIEW
override public function onRegister():void
{
// Listen for Views to be added to the ViewNavigatorApplication
app.addEventListener( Event.ADDED, handleAddedEvent );

            
// Mediate the firstView (currently the LoginView)
sendNotification( AppConstants.MEDIATE_VIEW, app.getActiveView() );
}

handleAddedEvent():
:
// HANDLE ADDED EVENTS (Event.ADDED)
private function handleAddedEvent( event:Event ):void
{
if ( event.target is View ) {
sendNotification( AppConstants.MEDIATE_VIEW, event.target );
}
}

The TabbedViewNavigator allows multiple navigators, but the ViewNavigators may not need to be mediated themselves. You can probably follow a similar pattern to the above example, just with TabbedViewNavigatorApplication instead of ViewNavigatorApplication.

BTW, a refinement of the above example appears in the ActionScript Developer's Guide to PureMVC which will be published by O'Reilly later this month.

-=Cliff>
« Last Edit: December 14, 2011, 05:14:47 by puremvc » Logged
purenewb
Newbie
*
Posts: 2


View Profile Email
« Reply #26 on: December 14, 2011, 04:00:48 »

Thanks Cliff. Looking forward to the book!
Logged
gary.paluk
Newbie
*
Posts: 3


View Profile Email
« Reply #27 on: January 19, 2012, 06:41:48 »

Hi Cliff,

I'm just trying to solidify the way that you would access the methods in MyMobileApp? The reason I ask is that if you are mediating a view, lets say you default first view; LoginView, we shouldn't directly access the MyMobileApp in order to call these methods so what is the approach here?

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



View Profile WWW Email
« Reply #28 on: January 20, 2012, 09:56:52 »

Gary,

if you are mediating a view, lets say you default first view; LoginView, we shouldn't directly access the MyMobileApp in order to call these methods so what is the approach here?

There is no problem with the mediator calling methods on the view component it tends. Along with setting and getting its top level properties and listening to it for Events, calling methods is the recommended way to communicate with the component. Calling a method on the component helps the Mediator be able to get (or set) what it needs from the component without having to break the encapsulation of the component by 'reaching into it' and manipulating its internals directly.

In the code I posted above, you can see in the ApplicationMediator.onRegister() method:

:
  // Mediate the firstView (currently the LoginView)
   sendNotification( AppConstants.MEDIATE_VIEW, app.getActiveView() );

The application exposes a method that the ApplicationMediator can call to get the active view, which it sends off in a note handled by a command that will do the registration.

Does that answer your question? I'm not sure I was completely clear on what you were looking for...

Cheers,
-=Cliff>
« Last Edit: January 20, 2012, 10:04:06 by puremvc » Logged
Pages: 1 [2]
Print