View Mediator Created, Destroyed, Created Again, and then Init Called Twice

david.whittingham's Avatar

david.whittingham

17 Jul, 2013 07:27 AM

Hi,

I'm having an issue where a child view is being mediated twice. I think I've somewhat tracked down the cause, but I don't know how to solve it.

The child view is just a component in the MXML on the parent view. The parent view uses multiple states, and I think this is where I hit trouble. The parent view is placed on stage, and a mediator is created for the child view. Flex then seems to fire the event for the parent view's initial state, which seems to cause the child's views mediator to call destroy(). A new mediator for the child view is created, and then the initialize function is called for both the original mediator instance (even though destroy has already been called) and the new mediator instance. This sets up all the events twice, causing mayhem.

If I set the mediator's autoRemove setting to false, this doesn't happen, but that seems like the wrong way to solve this problem. Any help would be appreciated.

  1. Support Staff 1 Posted by Ondina D.F. on 18 Jul, 2013 02:27 PM

    Ondina D.F.'s Avatar

    Hi David,

    if you had something like this:

    <components:SomeView id="someView" includeIn="firstState, secondState"/>
    

    then Flex would remove the component from stage before re-parenting it, as you noticed, and Robotlegs would react as it should(destroy / create mediators).

    The only solution that comes to mind right now is this:

    <components:SomeView id="someView"/>
    

    Note that I didn't include the includeIn statement! Strangely enough, Flex won't remove the view when the state changes.

    Then when you change the states, if you don't want someView to be visible in secondState, you change its visibility:

    if(currentState == "firstState")
    {
        someView.visible = true;
        currentState = "secondState";
    }
    else
    {
        someView.visible = false;
        currentState = "firstState";
    }
    

    Or, just don't use states;)

    Ondina

  2. 2 Posted by david.whittingh... on 19 Jul, 2013 01:09 AM

    david.whittingham's Avatar

    Hi Ondina, thanks for replying.

    The thing is, I'm not using the includeIn attribute on the child view. However, it's parent container does get enabled/disabled with state changes.

    My issue isn't so much that the mediator gets created/destroyed with state changes, its that initialize is called on the child view after destroy is called..

    Edit: Furthermore, I just tried out your advice of not using states, and it's still being mediated twice, exactly the same as before with initialize being called after destroy.

  3. Support Staff 3 Posted by Ondina D.F. on 19 Jul, 2013 07:27 AM

    Ondina D.F.'s Avatar

    Hey David,

    Are you using any other libraries/plugins/utilities - Starling, tweening, effects, e.t.c.?
    How are you adding your child view to its parent, through actionscript or in mxml?

    My issue isn't so much that the mediator gets created/destroyed with state changes, its that initialize is called on the child view after destroy is called.

    But if initialize is called, it means that a new mediator is created for the re-parented view.
    Add handlers in your child view for the ADDED_TO_STAGE and REMOVED_FROM_STAGE events to see what happens when the state changes.

    Could you attach the project or a stripped down version that replicates the issue?
    Or paste all relevant code ( for the parent and child mediators + views)?

  4. Support Staff 4 Posted by creynders on 19 Jul, 2013 07:58 AM

    creynders's Avatar

    > then the initialize function is called for both the original mediator
    instance (even though destroy has already been called) and the new mediator
    instance.

    If that's the case then something's definitely wrong. As Ondina said, could
    you provide a bare bones version which exhibits this behaviour?

  5. Support Staff 5 Posted by Ondina D.F. on 19 Jul, 2013 12:46 PM

    Ondina D.F.'s Avatar

    Furthermore, I just tried out your advice of not using states, and it's still being mediated twice, exactly the same as before with initialize being called after destroy.

    Now I think that your mediator is not getting destroyed at all, actually.
    You'd have to use the Profiler to verify that.

    Usually, a mediator can't be destroyed if it holds a reference to its view in a way or another.

    Are you, by any chance, listening for events from view like this (which is not a good practice in my opinion) :

    view.someButton.addEventListener(MouseEvent.CLICK, onSomethingHappened);
    

    If you do, you have to remove the event listener manually in your destroy() method. Robotlegs removes only the event listeners added via addContextListener and addViewListener when destroy() is running.

  6. 6 Posted by david.whittingh... on 22 Jul, 2013 02:24 AM

    david.whittingham's Avatar

    Back in the office after the weekend.

    Are you using any other libraries/plugins/utilities - Starling, tweening, effects, e.t.c.?

    I load the the default bundle. I am using the Robotlegs State Machine utility, but not within the plug-in architecture of RL2.0+.

    How are you adding your child view to its parent, through actionscript or in mxml?

    MXML

    Could you attach the project or a stripped down version that replicates the issue? Or paste all relevant code ( for the parent and child mediators + views)?

    I can possibly do that. The project is actually a plug-in for a third-party closed-source application, so I will have to re-work a few things to build up a test case that can exist separately from that environment. The third-party app just loads the plugin as a Flex module, so I there isn't too much to do. I'll do my best to get around to this soon.

    Are you, by any chance, listening for events from view like this (which is not a good practice in my opinion)

    view.someButton.addEventListener(MouseEvent.CLICK, onSomethingHappened);

    I'm not, I would also consider this bad practice. All interaction between the view and the mediator is through normal function calls exposed on an interface for the view. In the mediator, the only listeners I setup are via addContextListener and addViewListener. The only reference to the view is injected in, via matching the view's interface to the mediator in the mediator map.

  7. Ondina D.F. closed this discussion on 17 Aug, 2013 10:52 AM.

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