Child sprites' mediators are never destroyed, they keep catching events from context!

ikbalnamli's Avatar

ikbalnamli

20 Jun, 2014 01:09 PM

Hi guys,
I have a situation that I couldn't find a way out yet even I googled for like a week. I am either making a very basic mistake or I am expecting something that RL2 doesn't provide. Therefore I will start with a question:

1) I have a parent view* that is being mediated. This view has a child view that is being mediated with its own mediator. The question is that when I remove the parent view from the stage, should I expect the child view's mediator to be destroyed?

Well if the answer of this question is a YES, then I have a problem. If it is a NO, is there an option to turn this on or should I remove each children of this parent view from the stage one by one? I will put here a sample of code in order to make it easy to understand.

The code sample below is a bit complex from the example above, there are mediators that extend from each other. But I think the problem is the same for both examples.

    // VehicleView, SpeedPanel extends from Sprite, 
    // CarView extends from VehicleView

    // VehicleMediator, SpeedPanelMediator extends from Mediator
    // CarMediator extends from VehicleMediator

    // CarView owns a SpeedPanel component
 
    mediatorMap.mapMatcher(new TypeMatcher().allOf(VehicleView, CarView)).toMediator(VehicleMediator); 
    mediatorMap.map(SpeedPanel).toMediator(SpeedPanelMediator);

carView.parent.removeChild(carView);

// When the line above is executed, CarMediator gets destroyed. However SpeedPanelMediator is not destroyed and continues catching events from the context, consider SpeedPanelMediator below:

    public class SpeedPanelMediator extends Mediator
    {
    [Inject]
    public var view:SpeedPanel;
    override public function initialize():void
    {
        injector.injectInto(view);
        addContextListener(SpeedEvent.UPDATE, onSpeedUpdated);
    }
    private function onSpeedUpdated(e:SpeedEvent):void
    {
        view.updateSpeed(e.speed);
    }
    }

Even if the CarView is removed from the stage and CarViewMediator is destroyed, the SpeedPanelMediator is never destroyed and the onSpeedUpdated method continues to be called.

I want the SpeedPanelMedatior matched to my SpeedPanel object to be destroyed when the CarView gets removed from the stage.
I am able to achieve this manually by removing SpeedPanel from the CarView (ex: carView.removeChild(speedPanel). Is that the way it is?


  • All views are subtypes of Starling Sprite.
  1. Support Staff 1 Posted by Ondina D.F. on 20 Jun, 2014 04:05 PM

    Ondina D.F.'s Avatar

    Hi,

    Thanks for showing some code and for explaining the workflow! That's always a good idea when asking a question, but not everyone does that:)

    The question is that when I remove the parent view from the stage, should I expect the child view's mediator to be destroyed?

    The answer is Yes, if the child view has been removed from stage as well.
    But if there are still references to views and/or mediators they will be kept alive.

    I want the SpeedPanelMedatior matched to my SpeedPanel object to be destroyed when the CarView gets removed from the stage.

    Normally, SpeedPanel would be removed from stage when CarView gets removed.

    First thing to check is if SpeedPanel has been indeed removed from stage and garbage collected. Use something like Flash Builder profiler to find loitering objects and which class has a reference to another class.(don't forget to force the gc if you use the profiler)

    If SpeedPanel is still there, look at what could keep it alive. Look at this discussion for details:
    http://knowledge.robotlegs.org/discussions/robotlegs-2/8306-old-med...

    In your SpeedMediator you have this line:
    injector.injectInto(view);
    What are you injecting into the view?

    Are you using as3-signals? If yes, don't forget to remove their listeners!!

    I am able to achieve this manually by removing SpeedPanel from the CarView (ex: carView.removeChild(speedPanel). Is that the way it is?

    It is a good idea to have a destroy()/clean() method inside of views, that takes care of removing all possible references to the view in order for it to get garbage collected.
    So, yes, you can do that, but first try to see what's keeping it alive.

    Well if the answer of this question is a YES, then I have a problem. If it is a NO, is there an option to turn this on or should I remove each children of this parent view from the stage one by one?

    Maybe I misunderstood your question? I'm not sure what you want to be kept alive and what should get destroyed. Do you want to manually mediate/unmediate views?

    In case you can't find a solution, try to reproduce the issue in a bare-bone project, where you have only the 3 views/mediators in question. If you want, you can attach the simplified app as a zip and I'll take a look at it. Also, try your scenario with simple Sprites that don't extend a Starling sprite. Maybe Starling is the culprit ;) Are you using one of the Starling extensions for robotlegs?

    Let me know how it goes.

    Ondina

  2. 2 Posted by ikbalnamli on 23 Jun, 2014 01:59 PM

    ikbalnamli's Avatar

    Hi Ondina,

    Thank you for your reply. I have found a solution, yay! Let me answer some of your questions to clarify the case here:

    I am using as3-signals, I remove their listeners carefully.
    injector.injectInto(view); This line is for PostConstruct.

    I am using SARS (Starling extension for robotlegs).

    Well after some investigation and debugging about mediators I ended up with the MediatorManager.as class of robotlegs and I realized that Event.REMOVED_FROM_STAGE listener is added to every flash DisplayObject in the addMediator function. Since I use starling DisplayObject these listeners which are responsible for destroying the mediators are never added. Let me put the corresponding code snippet here:

    public function addMediator(mediator:Object, item:Object, mapping:IMediatorMapping):void
            {
                const displayObject:DisplayObject = item as DisplayObject;
    
                // This if statement never becomes true, since my display objects are starling display objects
                if (displayObject && mapping.autoRemoveEnabled)
                    displayObject.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
    
                // Synchronize with item life-cycle
                if (itemInitialized(item))
                {
                    initializeMediator(mediator, item);
                }
                else
                {
                    displayObject.addEventListener(CREATION_COMPLETE, function(e:Event):void
                    {
                        displayObject.removeEventListener(CREATION_COMPLETE, arguments.callee);
                        // Ensure that we haven't been removed in the meantime
                        if (_factory.getMediator(item, mapping) == mediator)
                            initializeMediator(mediator, item);
                    });
                }
            }
    

    Well I supposed that SARS should have resolved this issue, after some investigation I found out that SARS is not aware of children sprites that are removed.

    So I decided to fork your MediatorMap extension and changed imports from flash.display.DisplayObject to starling.display.DisplayObject :)

    For now everything works like a charm.

  3. Support Staff 3 Posted by Ondina D.F. on 27 Jun, 2014 08:19 AM

    Ondina D.F.'s Avatar

    Sorry for the delay in replying.

    Well I supposed that SARS should have resolved this issue, after some investigation I found out that SARS is not aware of children sprites that are removed.

    I have no idea whether Vjekoslav is still maintaining the SARS project, but trying to open an issue on github wouldn't hurt:)

    I'm not familiar enough with SARS and Starling to be able to see if there is a better solution to your problem, especially one that doesn't require changing robotlegs' classes.

    But, who knows, maybe the solutions I presented in the discussion mentioned below could inspire you, despite my Starling-newbiness ;)

    http://knowledge.robotlegs.org/discussions/problems/3815-injector-i...

  4. Ondina D.F. closed this discussion on 11 Jul, 2014 08:10 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