Code Slinger: A DP Blog

Food for thought, using the Flex framework for dependency injection

Posted At: December 28, 2009 8:12 PM | Posted By: Michael Labriola
Related Categories: Adobe Flex

Dependency injection with Flex UI components can be tricky business. Not just doing it, there are a lot of strategies for that, but to do it without causing performance degradation and unnecessary work on the part of the framework and ultimately flash player. To understand why, we need to discuss a bit about the whole component life cycle.

When a component is first instantiated, its constructor is executed and any local variables that might have been declared with initial values are set, etc., but the most important stuff… the stuff that makes a component a Flex component hasn’t happened yet and it won’t anytime soon. Properly written Flex components do the balance of their work after they are added to the display list. Back when I first started yapping about this stuff most of these life cycle methods weren’t well known, but today there are a lot of great resources on them, so I am just going to stick to the basics.

The methods I care about are createChildren, measure, commitProperties and updateDisplayList. Each of these methods is called by the Flex framework after the component is on the display list. With the exception of createChildren, you can almost think of these methods as being scheduled. They get called by the framework, at an appropriate time for optimal Flash player performance, if the component itself or some outside force deems it necessary.

To take advantage of this scheduling and to ensure you don’t have timing issues, a properly architected Flex component waits to create any static visual children until the createChildren method is called. It waits to make visual changes to the component until the updateDisplayList method. When a property is changed on the component that could affect one of the components children, i.e. the textinput inside of a datefield, the component saves off this change and applies it when commitProperties is called. Finally, the component aggregates information about its size and reports it (but never, ever changes it) during the measure method.

The reason I mention all of these things is that there is a fair amount of work that starts happening the moment the component is added to the display list. From that point on, all of these methods are called and changes to the component, especially those involving the amount of space it takes on the screen, can cause major amounts of rework. (If I change the size of a button in the middle of the page, I may need to size and layout the whole page again). You would never know this from the Adobe docs, but the creationComplete event is likely the worst place you can do many things and that is for this same reason. Everything is sized, positioned and ready to do… then you cause it all to change again.

That means that, to perform optimally, I really should set all of the properties and make all of the changes I can to a component before it is on the display list. After I do, every property change that happens can have a much bigger impact. This all gets even worse once data binding figures into the mix. Now changes to public properties of my component may very well end up causing other components to redo this same work and lay out their interface again. It can all get bad, and quickly.

Okay, a bit more info. When you declare a bunch of components in MXML, the Flex precompiler actually creates an array of something called component descriptors. Component descriptors basically indicate the class you wanted to build (e.g. VBox), any properties or styles you want set on the VBox (e.g. width, backgroundColor) and then it holds an array of the descriptors for any children of the VBox. So, basically, your MXML becomes a big set of arrays of descriptors. The interesting words I said above are ‘properties and styles’. You see, Flex already injects properties and styles into new instance during the creation process. In fact, if you look at the code for Container, you will see that it creates a new instance of whatever class you need (e.g. VBox) and then loops through all of the properties and sets them on the component. This all happens, very wisely, before the component is added to the display list and before any bindings on the child are initialized and executed. All that means that the way the components are created by Flex allows you to inject properties at runtime but do it in a way that does not cause unnecessary refreshes of the display, resizing or other such malicious actions.

Wouldn’t it be nice if you could tap into that code? Well, you can of course, because this is Flex and with enough desire you can basically do anything. That doesn’t mean, of course, that our good friends at Adobe couldn’t make this a whole lot easier if methods that can be overridden weren’t touching properties that can’t be… but that is another issue for another time.

In this example I am just overriding the methods of a VBox, but you could choose to extend every container, monkey path Flex, or even recompile the framework should you want this functionality to be part of ever container. Oh, before I even begin, let me just clarify this. I am not showing you a dependency injection framework or even a complete solution; I am showing you a concept. It does work as I have used this inside of my own framework code for the last several years, but the concept is the important part so that’s what I wanted to share.

Okay, first things first, Container has a method named createComponentForDescriptor. This gets called for every single child of the Container when it is time to build that component. So, we are going to override this method. Why? Well, several reasons. We are going to make a hook to modify the component descriptor before it gets created. Perhaps we will also add something in here which decides if the component should even be created at all.

override public function createComponentFromDescriptor( descriptor:ComponentDescriptor, recurse:Boolean):IFlexDisplayObject { var uiCompDesc:UIComponentDescriptor = descriptor as UIComponentDescriptor; var permission:String = securityManager.getPermissionsForDescriptor( uiCompDesc ); if ( permission == SecurityManager.NOT_ALLOWED ) { return null; } var newDescriptor:UIComponentDescriptor = securityManager.modifyDescriptor( uiCompDesc, permission ); newDescriptor = diManager.modifyDescriptor(newDescriptor ); return super.createComponentFromDescriptor( newDescriptor, recurse ); }

Alright, what in the world is going on in this code. Let me explain a bit. When this method is called, it is passed a descriptor that it needs to build. So, first thing we are doing is calling some fictitious security manager which is going to let us know if we can build the thing at all. How does it figure that out? That’s not up to me. Point is that you have a hook where you can ask some other object if you are allowed to build this new component. If you don’t understand why you would want to do that, no worries, it just means you aren’t writing apps that need that granular control, however, trust me, there are plenty of apps which need this. If you aren’t allowed to build it, you simply return a null. Flex happily goes onto the next component never looking back. In this way, entire branches of components can be created or not.

Next thing that happens is that we pass this component descriptor to a method on our fictitious security manager and ask it to modify the descriptor as needed. What does this mean? Again, it’s a hook for your use. Imagine a scenario where you are asked to render a textinput. If the user has permission, you do so. If they don’t have permission to edit it, you (at runtime) decide to create a Label instead. This is all done without changing your MXML code.

Last thing we do is pass this modified descriptor to our fictitious dependency injection manager. This manager can use things like introspection, lookup or whatever else you might imagine to further modify this descriptor adding new values, removing old ones or doing something I haven’t imagined to the descriptor.

At the end of the method, we simply call our super class and pass along the modified descriptor. This causes Flex to go and execute the code which creates the class, injects the properties and adds it to the display list. So, we get the benefit of runtime modification of the components without the performance overhead of doing it once they are on the display list. If you care about such things, this is pretty cool. If you don’t, I won’t hold it against you.

Now you can do many more things to make this cleaner. Perhaps hide the container if no children are created so it is cleaner on the screen. Perhaps there are other managers or objects which should get a turn messing with the descriptor. Point is that this is a different way of looking at injecting properties by using the code that already existing in the framework to do this, rather than existing completely on the outside. Before anyone chimes in, yes, this is a Flex only solution.. and, as I already mentioned, it isn’t a solution, but an idea I wanted to share.

Final thing, with just the tiniest modifications to the Flex framework, Adobe could provide us the ability to specify things like that DI manager at runtime. Then this could be done generically enough that we wouldn’t be recompiling, monkey patching or maintaining a dozen overridden containers. Food for thought.


Labriola
Share and Enjoy:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • PDF
  • RSS
  • email
  • Technorati

Comments (5)

5 Responses to “Food for thought, using the Flex framework for dependency injection”

  1. Nick Collins says:

    Great article, Mike! I did something very similar to this for a client, for some of the very reasons you mentioned, controlling whether components were created at all based on user permissions.

    I’d experimented with it in the past for dynamically building a form wizard based on an external XML definition, however I ran into some issues hand-crafting the component descriptors. In the debugger, my hand-crafted component descriptors looked nearly identical to the ones generated by the pre-compiler, but would always throw runtime exceptions.

    Perhaps in a future post you could go into how one might hand-craft new descriptors, as opposed to modifying existing descriptors, and injecting those into the array to be instantiated?

  2. brett says:

    This was very interesting thanks for the Christmas/New Year present. Could you make a simple example as a picture is worth a thousand word ;) an other thing,"Finally, the component aggregates information about its size and reports it (but never, ever changes it) during the measure method." how do you force a size refresh on a component that echo through the all display list, I have had issue when i re-sized a component (ei image tag) "physically" and the new size were not being taken into consideration.

  3. Mike,

    Nice, I never really thought about that spot for what you are doing. I love component dev, truly the legos of the Flex/Flash castle.

    It has been 4 years since Flex 2.0 and I am still wondering when the community will embrace component development as a first class citizen.

    Mike

  4. Tom Sugden says:

    Hi Mike,

    Great article, but it does beg the question: precisely what changes to the Flex SDK would best support dependency-injection (or other forms of descriptor processing)?

    It’d certainly be handy to have a hook similar to the ObjectDefinitionDecorator interface in Parsley (http://www.spicefactory.org/parsley/docs/2.0/manual/extensions.php#decorators_interface), through which a descriptor could be modified, additional discriptors created and lifecycle listeners attached.

    Best,
    Tom

  5. rambojones says:

    Hey, something is wrong with your site in Opera, you should check into it.

Leave a Reply