modular popups

barrusj's Avatar

barrusj

19 Jan, 2014 05:44 AM

As a continuation of the discussion modular-popups-round-2 - I'm working on the same project as Beau and we found that a custom MVCSBundle without StageSync worked in preventing the context from being destroyed when the popup closed.

However, when the "cached" popup was reopened (added to the stage) a mediator would not be created/attached to it. It appears that the root context view only expects to have a mediator attached once. We were able to get past it by manually requesting the mediator map to handle the view again in the Module class (shown below). This seems like a rather clunky workaround and I'm wondering if there is a better way to do this.

private var checkoutModuleContext:CheckoutModuleConfig;

private function onPreinitialize():void
{
    //configure the context
    checkoutModuleContext = new CheckoutModuleConfig(this);
}

private function onAddedToStage(event:Event):void
{
    if (checkoutModuleContext && event.target == this) {
        var mediatorMap:IViewHandler =  checkoutModuleContext.context.injector.getInstance(IMediatorMap);
        mediatorMap.handleView(this, CheckoutModule);
    }
}
  1. Support Staff 1 Posted by Ondina D.F. on 20 Jan, 2014 12:23 PM

    Ondina D.F.'s Avatar

    Hello,

    I've read the posts related to this one. You're citing Beau's posts, so I think you've seen my modular example on github, right? I'm loading a module in a popup, where only the module has its own context. The popup is just a container created in the parent context. There are no memory leaks in my example.
    If I understand correctly, you create a context for the popup, which then loads a module with its own context.
    The problem with a popup that has its own context is that when you remove the popup from the stage you need to let the same viewManager that has added it through
    viewManager.addContainer(titleWindowInstance); remove the titleWindowInstance.

    And that viewManager is the parent context's viewManager!!

    In this post http://knowledge.robotlegs.org/discussions/robotlegs-2/7627-modular... , Beau is trying to remove the titleWindowInstance in the command that has created the popup. That won't work, because the command is already "gone" by the time the popup gets closed. Thus, the titleWindowInstance won't get gc-ed.

    You've tried to cache the popup to remedy this situation (memory leaks). But, in my opinion, that's not really a good idea. It makes things unnecessarily complicated.

    Can you tell me, why do you need a context for the popup? Just curious.

    If you want to keep your setup, with a context for your popup, I suggest to let it be destroyed when the popup leaves the stage. I don't see any advantages in using a cache. Can you convince me of the contrary?;)

    So, if you decide to destroy popup's context, you have a few choices:

    • you create your popup inside a mediator in the parent context and add something like this: titleWindowInstance.addEventListener(CloseEvent.CLOSE, onTitleWindowClose);

    Inside of onTitleWindowClose:
    viewManager.removeContainer(event.currentTarget as DisplayObjectContainer);

    • you create a named mapping for the IViewManager in your parent context, and inject the viewManager into your parent-context mediator or command that's creating the popup and into popup's mediator:

    [Inject (name="parentViewManager")] public var viewManager:IViewManager;

    You add the titleWindowInstance to the shared viewManager in your parent context (mediator or command) and remove it from the shared viewManager inside of the destroy() method of your popup's mediator.
    This way the popup view will be destroyed, and so will be its mediator and context. No memory leaks!
    If it's confusing, let me know, and I'll try to give you more details or to explain it better.

    Ondina

  2. 2 Posted by barrusj on 20 Jan, 2014 09:10 PM

    barrusj's Avatar

    The popup module is the checkout process for an ecommerce site. The reason for using it is to improve application load time. Given the amount of hassle flex modules are, I'm not sure if the effort is worthwhile.

    The module context holds the checkout model with all the users checkout data. If we destroyed the context and unloaded the module when the popup is closed, upon reopening, the user would have to reenter information.

    I suppose we could keep the checkout data model in the main application instead of the module and destroy the module when it's closed, but then you pay the cost of loading the module every time it is opened.

    We have a separate module for an account details popup that we do want the module to be unloaded and the context destroyed when the popup is closed and we do have this working correctly.

  3. Support Staff 3 Posted by Ondina D.F. on 21 Jan, 2014 08:47 AM

    Ondina D.F.'s Avatar

    If I needed to keep the popup's context alive, I wouldn't close it on CloseEvent.CLOSE. I would just change its visibility, false on closing, true on opening, and add another mechanism for closing and removing it from stage.
    Would it work for you?

  4. Support Staff 4 Posted by Ondina D.F. on 21 Jan, 2014 12:12 PM

    Ondina D.F.'s Avatar

    I've tried out your setup with a popup (TitleWindow) context that doesn't install the StageSync Extension.
    In order to have a mediator for the popup, I had to map the popup view to its mediator in the shell's context.
    I created the popup in a shell's mediator, where I also injected the IMediatorMap.

    [Inject]
    public var mediatorMap:IMediatorMap;
    
    ...
    
    private var titleWindowInstance:PopupView;//a TitleWindow
    
    private function onLoadPopupWithContext(event:ModulesLoaderEvent):void
    {
        if(titleWindowInstance!=null)
        {
            PopUpManager.addPopUp(titleWindowInstance, FlexGlobals.topLevelApplication as DisplayObject);
            mediatorMap.mediate(titleWindowInstance);
            return;
        }
    ...
    //here, create the popup, add it to the viewManager, etc
    

    That works just for the popup, meaning the context won't be destroyed and you can re-mediate the popup. I did not load a module the way you did, though.
    I still think that you are making your life much harder than it needs to be by adding a module to the PopUpManager :)
    As you said, Modules are problematic anyway. Combined with the PopUpManager they become a real pain...
    I'm curious to know, why do you think the way I loaded the module and presented it in a TitleWindow (in my example) is not good. As I said in my previous post, you could just hide the TitleWindow, so the module's context won't get destroyed. Do you really need the functionality of a popup (managed by the PopUpManager), or could you use another container, like a Panel, to present your module?

  5. Support Staff 5 Posted by Ondina D.F. on 21 Jan, 2014 01:42 PM

    Ondina D.F.'s Avatar

    I've investigated your scenario even further. I've created a module the way you did.
    Actually, things are easier than I thought.
    I've created the context inside creationCompleteHandler of the module:

    removeEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
    
    _robotlegsContext = new RobotlegsContext(this);
    

    The RobotlegsContext:

    context = new Context()
        .install(CustomBundle)//whithout StageSyncExtension
        .configure(MediatorsConfig, ModuleConnectorConfig)
        .configure(new ContextView(view));
    context.initialize();//!!!!!
    

    I've forced context initialization!!

    MediatorsConfig:

    mediatorMap.map(IModuleView).toMediator(SomeModuleMediator).autoRemove(false);
    

    I've set autoRemove to false !! That's all it takes, and as far as I can see, it works well, no memory leaks...
    I hope that helps.

  6. Ondina D.F. closed this discussion on 03 Feb, 2014 02:06 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