Hidden, mediated ViewStack Views being corrupted on event handle

Justin's Avatar

Justin

25 Apr, 2012 02:24 AM

All,

I'm in the 11th hour and hopeful that my fellow robotleggers can help me out of a jam.

I have several mediated views in an mx:ViewStack/s:TabBar. I am lazy loading the views (default ViewStack behavior) and some of the NavigatorContent instances are included/excluded via flex states. Everything seems to be wired fine. The views are shown/hidden appropriately and the mediators are created/disposed correctly. Also, I am coding to a view API that sets bindable private vars (i.e. not manipulating view components directly in the mediator) .

I'm seeing some strange behavior when trying to handle events on the hidden views. When I click back to the previously hidden view, it has been completely corrupted. For instance, I have a DataGrid were only the wire-frame is shown. Even the non-bindable header names are missing. Also, the view is completely unresponsive to user interaction. If the view has never been created, clicking on the tab will simply display a white container. The player even crashes on some occasions. All this an no stack traces or null pointer exceptions.

The best I can tell, Flex is not happy with me manipulating a view which it has hidden in the view stack. Are there any known issues with trying to do this? Seems reasonable.

Thanks to all in advance,
Justin

  1. Support Staff 1 Posted by Ondina D.F. on 25 Apr, 2012 07:26 AM

    Ondina D.F.'s Avatar

    Hey Justin,

    instances are included/excluded via flex states

    I think the Flex States are the problem. Views get removed from the display list and added again when the state changes. When Views are removed from the display list, their Mediators are removed as well, and then created again when their Views are added to the display list.

    If you take a look at the parameters of the mediatorMap.mapView, you can see that autoCreate and autoRemove are by default set to true.
    mediatorMap.mapView( viewClassOrName, mediatorClass, injectViewAs, autoCreate, autoRemove );
    You can change that, for example you can set autoCreate to true and autoRemove to false.
    In this case you will have to remove the Mediators manually, if need be.

    Is it possible that you are triggering some actions in your onRegister() , maybe a service call?

    Can you show us some stripped down code that shows the issue or even attach the app or a simplified example? I am willing to take a look at it. At least the code of a mediator on Register() ?

    Cheers,
    Ondina

  2. Support Staff 2 Posted by Ondina D.F. on 25 Apr, 2012 07:55 AM

    Ondina D.F.'s Avatar

    Another thought related to the Flex States and the Views/Mediators creation and destruction:
    I think that your Views and Mediators don’t get garbage collected for some reason (strong references of some kind), and that can cause memory leaks. You’ll have to make sure you’re removing all strong references to objects and event listeners.

  3. 3 Posted by Justin on 25 Apr, 2012 07:58 AM

    Justin's Avatar

    Ondina,

    Thanks so much for the reply.

    Funny you should mention the onRegister method. I saw some other posts regarding making service calls from this method and how it could be a bad idea. I definitely make calls to initialize the view in onRegister; however, I believe I am handling them in a null-safe, life-cycle safe manner in the mediator and view. In fact, the init events and any updates from other views flow through the same event handling and ui update path.

    Do you know of any known issues with the onRegister, init calls, and viewstacks?

    I could understand a NPE or RuntimeException, but the view corruption is just unsettling. On one occasion, I did see a script timeout exception. This could indicate some infinite (or very deep) bind/validation loop in the depths of flex.

    One last little nugget. In my debugging, I saw a mediator get disposed and another immediately get assigned on the same view instance (i.e. same memory addr). I know RL will do a little optimization if it was within the same frame, but this must have spanned a frame in this case. In any event, I still think my code should handle this gracefully (albeit inefficiently).

    If none of these avenues lead towards an answer, I can definitely look into simplifying the view logic and sending you the basics of what I'm trying to do. Sorry for the fire-hose of details. Didn't want to leave anything out.

    Thanks again for the help. These boards never disappoint,
    Justin

  4. 4 Posted by Justin on 25 Apr, 2012 08:20 AM

    Justin's Avatar

    Ondina,

    Re: GC and Listener clean-up:
    I am using the eventMap's map/unmap methods (with the defaults for capture, weakReference, ext) to manage my listeners. This is the correct approach for managing in RL correct?

    It definitely appears that Flex is caching my view for performance reasons.

    I may just have to roll my own viewstack with states and basiclayout to see if the problem is with that old container. No doubt I am pushing the limits with ViewStack, states, visible/includeInLayout. Oh and of course the views themselves are complex with many custom item renderers, etc. ;)

    Thanks again for the info. Heading offline for a bit of recovery, but will be back soon.

  5. Support Staff 5 Posted by Ondina D.F. on 25 Apr, 2012 08:35 AM

    Ondina D.F.'s Avatar

    You’re welcome, Justin:)

    I’ll try to address your questions later on today. Of course it would be better/easier (for me) to see the code. In case you don’t want to post your code publicly, I could make the thread private (you can do that too), so you can attach your app, and after I download the file I would delete it and make the discussion public again.

  6. Support Staff 6 Posted by Ondina D.F. on 25 Apr, 2012 03:37 PM

    Ondina D.F.'s Avatar

    Funny you should mention the onRegister method. I saw some other posts regarding making service calls from this method and how it could be a bad idea.

    The idea is to avoid having view logic in your Mediator, to avoid holding state, and to let it be just a bridge between Views and the rest of the application.
    But, I don’t think it’s a bad idea per se to dispatch an event from the Mediator’s onRegister() –to let other Mediators do something in response to it, or to trigger a command in order to set something on a Model or to call a Service.
    I guess, the discussions you saw were about accessing Models and Services directly from Mediators. Is it a good or a bad practice? There are many different opinions about this topic.
    Personally, I don’t inject Services into my Mediators, and whenever I can, I avoid injecting Models as well. And when I inject Models, I use interfaces. I keep my Mediators light and as free of logic as even possible. I’m a proponent of following the best practices, but I’m certainly not a purist.
    For example, I think that strictly loose coupling is not always achievable or even desirable.
    Following a standard way of doing things has many advantages, of course, and in my opinion, it’s an easy thing to do, actually. A lot more difficult is to decide what’s “best” in a certain context – there is a so-called “contextual practice” or “context driven development”. But I digress ;)

    After being added to the display list a View may need data from external resources right away.
    If you’d take a purist approach, you’d let the View (Component) dispatch an event whenever it needed data (in this case after it has been added to the stage), and its Mediator listening for that event would just relay it to the rest of your application, and when the data returns, the Mediator would pass it to its View.
    But the rl-Mediators get created in response to Views being added to the display list.
    onRegister() == View has been added to the display list already, and its sub-components’ creationComplete has fired.
    If you wouldn’t have to care about the sub-components, dispatching an additional event from the View upon its creation, to let the Mediator know that it needed data, would be an unnecessary extra step, in my opinion. You could do that within the onRegister() of the Mediator.

    But, usually, you would want to make a service call in order to get some data for the Views’ sub-components, i.e. data providers for lists, datagrids…so, you’d have to be aware of their life cycle and their readiness for receiving data.

    Using bindings and item renderers makes it even more complicated. Triggering a service call from the Mediator’s onRegister can be tricky due to the asynchronous nature of the responses. You can not know whether the data returns before or after the sub-components, especially complex ones, are ready to set their data providers. Item renderers are known for being problematic in this regard.
    Calling a service through an event dispatched from onRegister is ok (in my opinion), but it’s up to you to decide whether it’s a safe thing to do or if you have to wait until all sub-components have been fully initialized, created, added to stage and layed out.

    Do you need to make a service call every time the View gets added to the stage? If you needed it just the first time, then every other call would be superfluous and a possible cause of trouble.

    I am using the eventMap's map/unmap methods (with the defaults for capture, weakReference, ext) to manage my listeners. This is the correct approach for managing in RL correct?

    Correct, but usually, you don’t need to unmap the listeners manually. If there are no strong references to an object (for example adding listeners to views directly, instead of using the event map can lead to strong references) the listeners get automatically unmapped when the mediator runs its onRemove() method (autoRemove=true).

    I may just have to roll my own viewstack with states and basiclayout to see if the problem is with that old container. No doubt I am pushing the limits with ViewStack, states, visible/includeInLayout. Oh and of course the views themselves are complex with many custom item renderers, etc. ;)

    Yes, I think it’s a good idea to start with a simplified ViewStack and add features gradually.
    Changing states, setting visible, using includeInLayout, and complex item renderers as well can be problematic even without a framework ;)

    Let us know how it goes.

    Ah, I almost forgot. In case you’re using FlashBuilder, have you tried to run the profiler and let it find loitering objects?

    Hmm, long rant and I don’t even know if I answered all your questions.

  7. 7 Posted by Justin on 26 Apr, 2012 07:36 AM

    Justin's Avatar

    Ondina,

    I appreciate the long rant ;) I'm always interested in hearing everyone's opinions in the UI space. So many more options than just beans, crud, etc. in the middle tier.

    Speaking of the middle tier, that's where I've been so I haven't had much time to simplify my view and see if that helps my problem. I plan to tackle that in the coming hours so I will keep the board up-to-date. Unfortunately, the app and views are too complex to build, run, or even upload so I'm going to have to do the simplification step on my own. I really appreciate the offer to look through the code directly. I'm sure I'll be hitting up the boards with my findings tomorrow.

    Thanks for the tip on auto-removing listeners. I've been cleaning them up manually in the onRemove method. That saves me some code and some copy/paste errors of re-mapping in onRemove.

    As for onRegister and decoupling purity, I couldn't agree more with everything you said. I don't inject models/services, but I do issue data request events. The extra step of dispatching from the view is where my pragmatism overrides my quest for purity.

    creynders did mention Stray's relaxed eventmap, but, while it looked cool, it seemed like too much setup and ramp-up cost for my needs. The discussion board closed before I could thank him for the suggestion.

    But now I'm ranting! Thanks again and I'll keep everyone up-to-date.

    Thanks again,
    Justin

  8. Support Staff 8 Posted by Ondina D.F. on 26 Apr, 2012 07:57 AM

    Ondina D.F.'s Avatar

    Hey Justin,

    creynders did mention Stray's relaxed eventmap, but, while it looked cool, it seemed like too much setup and ramp-up cost for my needs. The discussion board closed before I could thank him for the suggestion.

    I re-opened it, so you can thank him:)
    (Actually, as the author of the thread you should be able to re-open a closed discussion as well, as far as I know)

    Thanks again and I'll keep everyone up-to-date.

    My pleasure! Looking forward to your feed-back:)
    Cheers,
    Ondina

  9. Ondina D.F. closed this discussion on 29 Jun, 2012 09:05 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