PureMVC Architects Lounge

PureMVC Manifold => Bug Report => Topic started by: Oscar on September 28, 2007, 10:19:23

Title: [ DEFUSED ] "facade.removeMediator" doesn't work properly?
Post by: Oscar on September 28, 2007, 10:19:23
Hi cliff,

i just wanted to test what happens, when you remove a Mediator.
So I took the HelloSprite Example, and added some Code.

In the "StageMediator.as" File on Line 93, I added "facade.removeMediator("sprite1");":

case ApplicationFacade.STAGE_ADD_SPRITE:
var params:Array = note.getBody() as Array;
var helloSprite:HelloSprite = new HelloSprite( spriteDataProxy.nextSpriteID, params );
facade.registerMediator(new HelloSpriteMediator( helloSprite ));
stage.addChild( helloSprite );
facade.removeMediator("sprite1"); // <----------  Remove the Mediator with the Name "sprite1" -----------------------

And in the "HelloSpriteMediator.as" File on Line 106, I added an trace:

private function onSpriteDivide(event:Event)
var params:Array = [ helloSprite.xLoc,

sendNotification( ApplicationFacade.STAGE_ADD_SPRITE, params );
trace(getMediatorName()); <--------------- Trace his own MediatorName ------------------------------

What I expects was, that the "sprite1" still moving around, but because his Mediator was removed, it will not add new "HelloSprite" Sprites,
and it will not trace his MediatorName anymore.

But this was not the case. Instead of this, it does the following:

- The Sprite "sprite1" stopped moving
- Now, when you move the Mouse over the "sprite1", it adds new "HelloSprite" Sprites.
- It still trace "sprite1", when you move the Mouse over it.

It seems, that the Mediator is not delete properly. But even maybe the Mediator is still there, why does the Sprite stop to move? The Code for moving is in the "HelloSprite" Class, not in the Mediator Class.

Is this behavior correct, or is there something wrong?   

Title: Re: "facade.removeMediator" doesn't work properly?
Post by: puremvc on September 29, 2007, 07:46:44

The removeMediator method does not guarantee that the Mediator itself will be removed from memory, only that it will no longer be notified by the View.

The reason the Mediator is hanging around is that the sprite is still alive and has a reference to the Mediator, since the Mediator placed event listeners on that sprite.

If you set a breakpoint somewhere after the removeMediator has taken place, and use the debugger to examine the mediatorMap and observerMap in the View, you'll find that the Mediator reference and its Observer instance are removed from the View. Had the View Component (the sprite) also been removed, there would be no more references to the Mediator and it would go away entirely.

Basically, this test doesn't mirror any real world use case. In a real application, the only real reason to remove a Mediator is if its View Component has gone away and the Mediator is therefore no longer needed.

For the sake of argument and completeness, I'm going to make a stretch of the imagination here and say, maybe there's a use case where you want to switch Mediators for a given View Component at runtime. Maybe you've 'turned on logging' and now you want a version of the Mediator that does logging, or some such.

In this case you would need to have the normal Mediator remove all the event listeners from the View Component first, then do facade.removeMediator to unhook it from the PureMVC View. Now it's a lonely little Mediator with no one to talk or listen to and it gets eaten by the Garbage Collector. Then you instantiate the new Mediator, passing it the View Component, and it takes over, logging everything. Obviously this would need to be done in a Command. And the Mediator would have to be given a method to cough up its View Component before being removed, so that the Command could pass it to the new Mediator's constructor.

Hope this clarifies removeMediator's purpose.