explorers' club

explorations in dev, science, sci-fi, games, and other fun stuff!

Life of a UIComponent

6 Comments

[UPDATE 2011.01.19]

Since the release of Flex 4 and the Spark framework, quite a lot has changed in the component life cycle.  Not that this logic has been removed, it has just been added to to accommodate the new Spark framework.  Hopefully I will find some time to update this or make a new post.

Reality Check

I have been developing in Flash for more years than I can remember and Flex since its inception.  Its amazing how with that many years under my belt, a professional title of “Sr. Flex Consultant” and a pretty good comprehension of the “engine” of AS3, I still don’t know some basic things.

Case in point:

I was browsing Kirupa’s AS3 forums to see if I could swing in and make someone’s day by solving their AS3 woes.  I found a guy who was basically trying to access child DisplayObjects on a DisplayObjectContainer from within the parent’s constructor.  Now I don’t know if he was trying to access children instantiated programmatically or those placed on the timeline (I assume the latter case), but the problem is a result of the child references being null during the constructor.  Seems like an easy solution right?  Just wait and then do a check then any subsequent logic if applicable, else wait some more.

I wanted to provide the guy some insight and so I thought, “you know a UIComponent is pretty damn straight forward”.  It even has a great method called childrenCreated that you can leverage.  But trying to find a solution from a UIComponent is quite difficult because the process isn’t as straight forward as I had assumed it to be.  I was amazed to realize that I hadn’t the clear understanding of what goes on under the hood of the MX framework as I had previously thought.  Anyway, to make a not so long story short, I present a detailed look into the life of a UIComponent.  BTW – all of this material can be found in the API docs as well as snooping around the MX code base.

Life of a UIComponent

Birth

  1. instantiation (aka. the constructor) – so there are a few differences when instantiating programmatically vs. declaritively (via MXML).  For now let’s make the assumption that we are dealing with programmatic instantiation.  The UIComponent doesn’t belong to the displayList, it is simply an object in memory.
  2. configuration – this may happen in the constructor or it may happen immediately after the UIC is created, but most properties needing initialization are set here as well as event handlers and other logic.  Keep in mind that some properties that are actual getters/setters can flag the UIC for invalidation/validation logic.
  3. adding to the displayList – in order to be a useful UIC, it needs to be brought into the fold.  So a parent UIC adds it to its displayList node.  Interestingly, the addng of a UIC to the displayList causes a lot of under-the-hood logic to take place.  For this section, the UIC in question is the one being added, not the parent.
    1. any former parent reference is removed (via DisplayObjectContainer(formerParent).removeChild(this))
    2. the UIC has some initialization performed on it regarding its document properties, styling, and some Module logic with regards to its new position within the displayList.
    3. the UIC is actaully added into the displayList.  This is done at a lower level withing the Flash player.  Doing so triggers an Event.ADDED event which is captured by the UIC’s parent.  This event is delayed and redispatched at a later point.
    4. the UIC’s initialize() method is called which drills down yet another chain of events:
  4. initialization – the UIC’s initialize() method is called which drills down yet another logic chain.  Note the possible recursive nature of this logic:
    1. the FlexEvent.PREINITIALIZE event is dispatched
    2. createChildren() is called
    3. childrenCreated() is called which trigger the invalidateProperties, …Size() and ..DisplayLIst() methods.  Note that the UIC may have been flagged for invalidation in step #2 (the configuration phase)
    4. accesssibilities are initialized
    5. the FlexEvent.INITIALIZE event is dispatched

Life within the display list

Up till now, the life of our UIC has been pretty easy to follow.  It and it’s parent have done quite a bit during the birthing process.  But now that the UIC has been flagged for invalidation, it gets a bit blurry.

  1. invalidation – most of the getters/setters in a UIComponent have some logic that says, “if the new value doesn’t = the old” then it is to invalidate the properties, size and/or displayList.  Most folks who do any component development make a great deal of use of these invalidation methods.  Most folks (like me) probably had assumed their wasn’t any logic that took place betw. invalidation and validation processes.  Oh but there is.An invalidation method is quite simple, it check two things, does the UIC (UIComponent hereinafter) have a parent and has a global-level ILayoutManager exist.  If both conditions are met, then the UIC hands itself over (as a parameter) to the ILayoutManager.   By doing these two checks a Flex app can conserve processing resources in case the UIC doesn’t reside within the displayList.  Why update something that isn’t visible to the user?  It does get updated, it just doesn’t get validated.
  2. managing the layout – Even though the name implies just layout-related tasks, the LayoutManager handles task related to invalidateProperties, invalidateSize and invalidateDisplayList.  By a system of boolean flags and queues, the LayoutManager goes thru the 3 pre-validation phases of telling each UIC in its queue.  Does UIC#2241782 need its size or properties validated?  Does UIC#99892 need to update its display list?  This kind of logic takes place here.  The queing mechanisms are complex and recursive so I won’t go into detail here, but suffice it to say works alot like a short-order cook.The really interesting thing about the LayoutManager is that it is main engine that drives the MX framework.  If any of you were ol’ Flash dev’rs and remember having to do onEnterFrame logic, this kind of logic is presented here but in very tricky fashion.  LayoutManager actually has a UIC that doesn’t reside in the display list.   This UIC is called the callLaterObject and as you can guess is used as the work horse for leveraging the ENTER_FRAME and RENDER events that get triggered.  At each triggering, the callLaterObject then reports back to the LayoutManager that we are in the next frame so we can now start the validation process on our queued UICs.
  3. validation – now that we have a new frame to work with, the LayoutManager will goto its needs-validation-queue and grab each UIC and issue validation orders.  Once that is done, the UIC in question gets added to yet another queue and a series of checks takes place before starting all over again for the next round of invalidation requests.

Summary

With the sort of logic that takes place for a mutltitude of UIComponents within an app, the geniuses over at Adobe have come up with a highly efficient system for managing resources while making the updates.  I hope this provides some insight.  And also sound off if you find that I am in error in writing this, as this was a journey of discovery for me as well.

J

6 thoughts on “Life of a UIComponent

  1. Hello jwopitz,
    Thanks for the brief explanation. I like it :).
    I am currently developing some components extending The UIComponent in Flex programmatically.

    Now some of the elements of the Component which gets created in createChildren needs to add assets from a RSL, i.e. a swf. I have used tink library manager to load this. outside the scope of the component.

    Now if I where to load the swf assets within my custom component, which may be required prior to createChildren method getting called, where and how should I go about. Is there any way out by defferring the call to createChildren on loading the assets first.
    I tried that by overriding initialize methodn and then doing a super.initialize() on assets load, but to my bad luck the updateDisplayList has already called out. when the initialized variable was actually false.
    So how do I go about? Any light that you can give.

  2. also you might want to override the getter for the initialized flag, making sure your assets have been loaded. Or override the createChildren method and make sure the assets are loaded before doing the createChildren logic, if not just callLater(createChildren)

  3. Thank,
    I have done the overriding the initialized flash but that does not help since the updateDisplayList does not get called when I do super.initialize() after my assets load, that causes the UI elements to be all loaded to 0,0.

    Thanks again.

  4. Ok I told you wrong about preinitialize event. In your constructor I would make a call to load your RSL. You also have a flag called isRSLLoaded. Override your your initialize call, checking if your isRSLLoaded is true, if not return. On the RSL load complete handler, set your isRSLLoaded flag to true, then call initialize.

  5. Thanks for your help 🙂
    I also did the same using a variable _assetInitializationFlag
    Which I also checked in updateDisplayList to be true to call a draw function. This draw function is overridden in the sub class and its done.

    Thanks again for giving me the pointer in the first post.

    Warm Regards
    Deepanjan Das

Leave a comment