The current parsley implementation is using the configure event to configure views – This is fine for a small application, but the reflection performed on the view hierarchy is heavy so it’s not ideal for large projects where performance is an issue.
To address this issue on a project I worked on recently,we created a custom inject tag which will inject the dependencies without performing the full configure on the view component. This works well, because you don’t really want to be dispatching or handling managed events from the view, and there isn’t really any reason to use [Init] or [Destroy] on the view either.
So how did we do this? Well, we implemented the tag, which specifies a couple of parameters, namely property and idRef – Property being the property name you want to inject into and idRef being the ID of the object you want to inject.
<Inject
property="someObject"
idRef="bob"/>
This tag replaces the configure event or the <Configure/> tag from Parsley.
The implementation is like this:
package parsley.tags
{
import flash.events.Event;
import flash.events.EventDispatcher;
import mx.core.IMXMLObject;
import org.spicefactory.parsley.core.context.Context;
import parsley.event.InjectEvent;
public class Inject extends EventDispatcher implements IMXMLObject
{
public var property : String;
public var idRef : String;
private var context : Context;
private var document : Object;
public function initialized(document:Object, id:String):void
{
if( !property || !idRef ) throw new Error("Cannot inject unless property and idRef is provided");
this.document = document;
document.addEventListener( Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage( event : Event ) : void
{
document.dispatchEvent( new InjectEvent( property, idRef ));
}
}
}
This tag dispatches an Inject event on the view object which bubbles up to the viewManager. We created a custom view manager which listens for the Inject event, and once it’s caught, it’s retrieving the object from the context and assigning it to the target of the event.
package parsley
{
import flash.display.DisplayObject;
import flash.system.ApplicationDomain;
import mx.core.UIComponent;
import org.spicefactory.parsley.core.context.Context;
import org.spicefactory.parsley.core.factory.impl.GlobalFactoryRegistry;
import org.spicefactory.parsley.core.view.impl.DefaultViewManager;
import parsley.event.InjectEvent;
public class InjectAwareViewManager extends DefaultViewManager
{
protected var parent : Context;
public function InjectAwareViewManager(context:Context, domain:ApplicationDomain)
{
super(context, domain);
this.parent = context;
}
override public function addViewRoot(view:DisplayObject) : void
{
view.addEventListener( InjectEvent.INJECT_EVENT, onInject );
}
protected function onInject( event : InjectEvent ) : void
{
var target : UIComponent = event.target as UIComponent;
var property : String = event.property;
var idRef : String = event.idRef;
if( idRef )
{
target[property] = parent.getObject( idRef );
}
event.stopImmediatePropagation();
}
}
}
This is far more performant than the configure tag, and serves the purpose in most view implementations.
To get this to work, you’d need to create a new ViewManagerFactory which returns the custom viewManager, and register this with the GlobalFactoryRegistry.
Simples, as Alexander from Meerkat.com says….
Thanks to Tom Sugden at Adobe for his thoughts on how to do this.
Edit: In Parsley 2.2 this feature is included as the tag – Use this rather than a custom implementation if you can.