How do I keep my view from getting extra mediators every time it is added to the stage?

Doug's Avatar

Doug

20 Apr, 2010 05:16 PM

I have a view on stage. It has a Mediator class mapped to it. If I remove the view from the stage, and add it again Robot Legs creates a second mediator. How do I avoid this?

  1. Support Staff 2 Posted by Shaun Smith on 20 Apr, 2010 08:30 PM

    Shaun Smith's Avatar

    Hi Doug,

    Fully automatic mediation ensures that mediators are created AND removed as view components are added to and removed from the display list. Each time a mapped view component is added to stage a mediator is created for it; and when it leaves, the corresponding mediator is removed.

    By default, a Mediator in Robotlegs acts as a stateless bridge between an on-screen view component and the framework. When a view component is not on-screen it is not mediated. Is there much point in updating an off-screen view component? Not usually.

    That said, there are times when the default behavior is not desired, in which case you can decide which parts you'd like automated, and which parts you will be responsible for yourself. You can control this behavior with the 3rd and 4th parameters of mediatorMap.mapView():

    /**
    * Map an IMediator to a view Class
    *
    * @param viewClassOrName The concrete view Class or Fully Qualified Class Name
    * @param mediatorClass The IMediator Class
    * @param injectViewAs The explicit view Interface or Class that the mediator depends on
    * @param autoCreate Automatically construct and register an instance of Class mediatorClass when an instance of Class viewClass is detected
    * @param autoRemove Automatically remove an instance of Class mediatorClass when it's viewClass leaves the ancestory of the context view
    */
    function mapView(viewClassOrName:*, mediatorClass:Class, injectViewAs:Class = null, autoCreate:Boolean = true, autoRemove:Boolean = true):void;
    

    http://github.com/robotlegs/robotlegs-framework/blob/v1.0.3/src/org...

    If you want to manually mediate a view component, set both autoCreate and autoRemove to false. You will then be responsible for manually creating the appropriate mediator by calling mediatorMap.createMediator(view);, and removing it with mediatorMap.removeMediator(mediator); or mediatorMap.removeMediatorByView(view).

    If you'd like mediators to be created automatically, but not to be removed when the view leaves the stage, set autoRemove to false, but be sure to remove the mediator when you no longer need it.

    Hope that helps,

  2. 3 Posted by Doug on 20 Apr, 2010 08:46 PM

    Doug's Avatar

    thanks, that looks like just what I need!

  3. 4 Posted by rob on 28 Apr, 2010 03:58 PM

    rob's Avatar

    I wanted to add that the reason the mediator is not being removed is because you aren't cleaning up your listeners. If you add an event listener, or a signal, to a view component then you have to make sure to clean those up When you remove the component or else the mediator will never actually be removed. I guess using the eventMap to add listeners would get around this issue.

  4. 5 Posted by Nikos on 06 Jan, 2011 05:03 PM

    Nikos 's Avatar

    So does RL look for listeners in the mediator and then not removing the mediator if listeners are there?

    Do I need to do anything extra to this mediator to ensure that it is removed properly?

    package views.mediators
    {

    import flash.events.Event;
    import flash.events.MouseEvent;
    
    import model.UserModel;
    import model.vo.Comment;
    
    import mx.controls.Alert;
    
    import org.robotlegs.mvcs.Mediator;
    
    import views.AddComments;
    import views.events.LogoutEvent;
    import views.signalz.AddCommentSignal;
    
    public class AddCommentsMediator extends Mediator
    {
    
        [Inject]
        public var viewObject:AddComments;
    
        [Inject]
        public var userModel:UserModel;
    
        [Inject] 
        public var addCommentSignal : AddCommentSignal;
    
    
    
        override public function onRegister():void
        {
            eventMap.mapListener(eventDispatcher, LogoutEvent.LOGOUT,handleLogout );
            viewObject.signal.add(handleADD_COMMENT);
    
    
        }
    
    
    
        private function handleADD_COMMENT(text:String):void
        {
            var comment:Comment = new Comment();
    
            if(userModel.selectedApplicationUser){
    
                comment.SAMAccountName = userModel.selectedApplicationUser.SAMAccountName;
    
            }else{
    
                Alert.show("Please select a user");
                return;
            }
    
    
    
    
            comment.comment = text;
            comment.contributingSAMAccountName = userModel.loggedInUser.SAMAccountName;
            addCommentSignal.dispatch(comment);
        }
    
        private function handleLogout(event:Event):void
        {
            viewObject.onLogout();
        }
    
    }
    

    }

  5. 6 Posted by Stray on 06 Jan, 2011 05:10 PM

    Stray's Avatar

    Hi Nikos,

    you'll need to override onRemove to remove your addition to the signal. Robotlegs cleans up events, but not signals.

    public override onRemove():void
    {
        viewObject.signal.remove(handleADD_COMMENT);
    }
    

    btw - I'm guessing your signal isn't REALLY called signal, and your handler isn't really called handleADD_COMMENT because that would just be silly!

  6. 7 Posted by Nikos on 06 Jan, 2011 05:30 PM

    Nikos 's Avatar

    perfect mate , how come we need to do this before the mediator is removed automatically, guess the framework checks for references to mediators in mapped components

    viewObject.signal.remove(handleADD_COMMENT);

    guess I don't need to do this:

    override public function onRemove():void

        {
    
            eventMap.unmapListeners();
    
        }
    
  7. 8 Posted by Stray on 06 Jan, 2011 05:38 PM

    Stray's Avatar

    Signals are not part of the robotlegs framework. When you map an event through the eventMap it cleans up after itself in the mediator preRemove (this is the purpose of the eventMap).

    You've added to a signal on a view - how on earth would robotlegs automatically know what to do about that?

    Robotlegs also can't remove events that you've registered for directly - only those registered through the eventMap.

    Personally I use a SignalMediator base which has helper functions similar to the eventMap ones. Instead of doing

    view.someSignal.add(someFunction);

    I do

    addToSignal(view.someSignal, someFunction)

    and then the SignalMediator keeps track of these and unregisters them during preRemove.

    If you use signals a lot then this is a sensible step to take.

  8. 9 Posted by Nikos on 06 Jan, 2011 06:04 PM

    Nikos 's Avatar

    wow, your knowledge of RL is growing and impressive :)

    where is the SignalMediator base code?

    Still I'm not sure what stops RL removing the mediator even if I don't do
    viewObject.signal.remove(handleADD_COMMENT);

  9. 10 Posted by Stray on 06 Jan, 2011 08:10 PM

    Stray's Avatar

    Growing and impressive? Uh... hrm. Anyway...

    It's not that the mediator isn't removed, it's that the handler is still attached to the signal, and the mediator is not available for garbage collection because it is being held on to by the signal.

    The SignalMediator is my own implementation - personally I use one that also includes the relaxedEventMap, but you probably don't need that.

    Your best bet is to copy/paste from here:

    https://github.com/Stray/robotlegs-demo-StrategyGame/blob/master/src/org/robotlegs/mvcs/SignalMediator.as

    You have to use addToSignal() to map to your signals for the automatic clean up to work.

  10. 11 Posted by Nikos on 07 Jan, 2011 11:24 AM

    Nikos 's Avatar

    I see so we depend on garabage collection for mediator removal, does this not mean the possibility of it not beign removed in time for the old mediator to pick up the signal?

  11. 12 Posted by Stray on 07 Jan, 2011 11:39 AM

    Stray's Avatar

    No.

  12. 13 Posted by Stray on 07 Jan, 2011 11:48 AM

    Stray's Avatar

    We don't depend on garbage collection for mediator removal - we unmap everything manually, and delete as much as possible, but - as with any code in any situation in flash - if you leave references scattered around (like your signal handler mapping) then they will persist and the object will continue to exist. It won't keep firing eventMap mapped events, because these have been unmapped directly.

    It was *you* who was hoping that garbage collection would clean up your signal handler. The framework is fine.

  13. 14 Posted by Nikos on 07 Jan, 2011 12:37 PM

    Nikos 's Avatar

    good points :)

  14. 15 Posted by Nikos on 07 Feb, 2011 04:36 PM

    Nikos 's Avatar

    I find that in a lot of cases I dont want to auto remove my mediators, especially when I have a command that gets data that refreshes a lot of my models, which the mediators then listen to the changes and update the views. If the mediators get removed then I find having to add checks in the meditors on register to see if the data has changed or not to update the view.

    my 2c

  15. 16 Posted by Nikos on 07 Feb, 2011 05:45 PM

    Nikos 's Avatar

    If I do this:

    mediatorMap.mapView(ObjectiveViewer,MyObjectivesMediator,null,true,false);
    

    am I right in thinking that my mediators will still be created each time the view is added to the stage? I don't see any checks in the Mediator Map to see if mediators already exist:

        protected override function onViewAdded(e:Event):void
        {
            if (mediatorsMarkedForRemoval[e.target])
            {
                delete mediatorsMarkedForRemoval[e.target];
                return;
            }
            var viewClassName:String = getQualifiedClassName(e.target);
            var config:MappingConfig = mappingConfigByViewClassName[viewClassName];
            if (config && config.autoCreate)
                createMediatorUsing(e.target, viewClassName, config);
        }
    
  16. Stray closed this discussion on 13 Feb, 2011 04:17 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac