240 likes | 374 Views
Customizing the Flex Framework aka “How to get what you need.”. Deepa Subramaniam Software Engineer Adobe, MAX, 2007. How was Flex built for customization?. Performance and Customization was on the forefront of our mind when designing the Flex framework.
E N D
Customizing the Flex Frameworkaka“How to get what you need.” Deepa Subramaniam Software Engineer Adobe, MAX, 2007
How was Flex built for customization? • Performance and Customization was on the forefront of our mind when designing the Flex framework. • Don’t like one of our components? Write your own! • Customization “Buckets” • UI • Data Management • Data Display • Control Behavior
ActionScript classes to MXML tags • For the most part, MXML tags map to an ActionScript class • Every tag attribute turns into a property, style, event handler on the object • <mx:Button label=“Submit” /> • Some tags have no class mapping and are hard-coded into the compiler: • <mx:Script/> • <mx:Metadata/> • <mx:Style/> • Every MXML file corresponds to a new ActionScript class where the name of the MXML file is the name of the ActionScript class • You can see the ActionScript code that is generated with the compiler option: keep-generated-actionscript = true • MXML objects with id’s correspond to member variables of that ActionScript class • Recipe Example (source/asToMXML)
Bucket 1: Customizing UI • How often have we seen UIs like this! • Skinning and Styling infrastructure built into the framework at the component level • Effect infrastructure built into the framework at the component level • Use these mechanisms to change your application/component look and feel
Styling & Skinning • Styles are applied to individual components or across broad sets of components • <mx:Label color=“0xFFCC00” />, setStyle(‘color’, 0xFFCC00), External CSS Stylesheets, <mx:Style/> • You can only get so far with styling – at some point you will need to turn to skinning. • Skinning: Modifying appearance of a component by substituting in images, SWF files, or class files with drawing commands • Skins represent the look of a component in its different states • For more information, attend Peter Flynn’s session – Building Stunning Applications with Flex and CS3
Effects Architecture • Effect classes live in mx.effects.* package • Effects are paired with triggers which initiates a Flex effect on a target component • Default effects library include effects like: Wipe, Fade, Zoom, Glow, etc. • Effects are split into 2 categories: • Simple effects that do not require an effect to play over a period of time (ie: Pause, Sound, etc) – These effects extend mx.effects.Effect • Effects that play out over a period of time, like an animation (ie: Resize, Zoom) – These effects extend mx.effects.TweenEffect
Writing Custom Effects – Shake Effect • Can composite effects together via the mx:Parallel and mx:Sequence tags • Can subclass existing effects like a custom Wipe or a custom Zoom • Can write a new effect by extending one of the effect base classes (Effect or TweenEffect) • Would require creating a custom effect factory class and a custom effect instance class • Effect factory class manages the creation/destruction of the effect instance(s) • I want to create a custom “Shake” effect - similar to the Mac login effect when you enter an invalid username/password. How will I do this? Shake Effect Example – source/shakeCompositeEffect
Bucket 2: Customizing Data Management • Customizations can be built directly into the data management classes. • Custom dataDescriptor • Custom collection
Data Descriptors for hierarchical data-aware controls • Hierarchical data-aware controls include: Tree, Menu, MenuBar, AdvancedDataGrid • These controls support arbitrary data • Data Descriptors are used to walk the dataProvider and “describe” it to the control. Describes information like: 1. Is this node a branch or a leaf? – isBranch() 2. What attribute on a node describes child collection (the sub collection) – getChildren() • Can use a custom data descriptor to do things like the following: 1. Lazy loading of data/load on demand: Build up the sub collection when a folder is pressed in the getChildren() call of your data descriptor. 2. Hierarchical data does not fit the format supported by the default descriptor (ie: children field does not exist). Would extend DefaultDataDescriptor.
Managing data sets • Managing data in Flex is easy • Can use underlying ActionScript objects like Array, XML, XMLList as dataProviders to your data-aware controls. • Can use Flex classes to create collections: ArrayCollection, XMLListCollection, etc. • 2 interfaces for creating collections • IList: Simple interface for indexed access to linear data • ICollectionView: More advanced interface to access data that is not guaranteed to be linear • Data aware controls can take input from a dataProvider that is any of the objects mentioned above, or a derivative of those objects
Scenario: User IDs + Credit Scores = ? • 2 unique data fetches result in a single set of data that my DataGrid needs to display Credit Scores: 760 650 840 580 619 765 623 810 User IDs: 1982 8712 7672 5109 2314 8723 0989 I could pull down 1000 User objects and 1000 Credit Score objects and then take the 2 collections returned and merge them into a single collection of 1000 objects and then display, like, 12 in my DataGrid. Uhm. Yuck. That is a very wasteful and poorly performing way of doing, what is basically, a join operation on the client.
Solution: Write a custom collection! • I’ll write a custom collection that does the merging of the data on the client – this is a much better performing solution! • 90% of the time – I can write a custom implementation of IList since I know the following point is true: • My data allows me indexed access to a linear collection The 3 key points in doing the merge of n separate collections on the client are: • A getItem() on the merged collection does a getItem() on the sub collections and builds up the merged object • An add/remove/setItem() on the merged collection does the add/removeItem() on the sub collections. • Integrate the notification between the sub collections and the merged collection so the merged collection knows to update when one of the sub collections changes Custom IList example – source/mergedList
Bucket 3: Customizing data display • Three (long) or four (short) bullets go here to describe the image, diagram or screenshot in the pod above • ItemRenderers for List-based controls • Custom Validators • Custom Formatters
Item Renderers • Allows you a way to customize the view of the data for data-aware controls. • Drop-in item renderer: A component that implements IDropInListItemRenderer is specified <mx:DataGrid dataProvider=“{data}”> <mx:DataGridColumn dataField=“image” itemRenderer=“mx.controls.Image” /> </mx:DataGrid> • In-line item renderer – Specify an inline component that is used as the renderer. • mx:Component tag defines a new scope in the MXML file local to the item renderer. <mx:DataGridColumn dataField=“image”> <mx:itemRenderer> <mx:Component> <mx:VBox width=“100%” height=“140”> <mx:Button label=“{data.label}” labelPlacement=“outerDocument.placement”/> </mx:VBox> </mx:Component> </mx:itemRenderer> • Or specify an ActionScript or MXML Component as an item renderer • Read Alex Harui’s blog for insights into renderers: http://blogs.adobe.com/aharui/
Validators and Formatters • Validators – set of classes in the Flex framework to validate user input • Common validators include EmailValidator, PhoneValidator, ZipCodeValidator • Validators are bound to source objects and told which property on that object to validate • Validation is triggered by an event, by default valueCommit • Base class to extend when writing a custom validator: mx.validators.Validator • Formatters – allows formatting of data for display purposes, or to send back to the server, etc. • Common formatters include DateFormatter, CurrencyFormatter, NumberFormatter • Formatters are applied to controls • Formatting occurs by calling the Formatter.format() method. • Base class to extend when writing a custom formatter: mx.formatters.Formatter Custom Validator example – source/customWordValidator
Bucket 4: Customizing control behavior • You can always extend existing framework controls to customize behavior. We are not going to talk about this now. • Instead – lets look at a powerful technique where, at runtime, we can customize the behavior of objects based on the metadata that decorates them. In other words….Custom Metadata!
What is Metadata? • Metadata provides information to the MXML compiler about how your component is used • Ie: [Style(name="horizontalGap", type="Number", format="Length", inherit="no")] • Metadata decorates ActionScript classes and MXML files • For the most part, metadata is used only at compile time and is stripped out of the SWF (by the linker) at optimization time so that SWF size is smaller. • By default, compiler keeps some metadata in the swf: Bindable, Managed, ChangeEvent, … • However, you the developer, can control this!
Instructing the compiler to preserve metadata • Flex 2: had to set compiler option to instruct the compiler which metadata tags should be preserved in the swf • mxmlc -keep-as3-metadata or <keep-as3-metadata/> tag in flex-config.xml • This was problematic: Users need to know what custom metadata to preserve when using a 3rd party library. So…… • Flex 3: SWC libraries now declare what metadata the linker should preserve when linking in code from that library. When a library is used to build an app, the app preserves the union of metadata from all the libraries that contributed code to the app. Custom Metadata Tag Example – source/customMetadata
Custom metadata scenario = Happy QE • My company has a homegrown testing library. • As developers write custom components, they add “testing directives” into their ActionScript and MXML code that instruct the test harness what test methods to call. • These “testing directives” are custom metadata tags that decorate testable objects • All QE has to do is run the test harness and those components decorated with testing metadata get their test methods invoked automatically! • Example
Patching the framework • Sometimes you find bugs in the framework… • There are a few options available to you for how you can choose to “patch” the framework for your immediate use.
Fixing bugs in the framework • First and foremost – file a bug (and enhancement requests too) • http://bugs.adobe.com • Vote on bugs – voting promotes the issue internally so that it is more likely to be fixed for the next drop • Option 1: Extend the offending control and insert your fix • Option 2: Copy the class into a separate package and use your “fixed” version of the component • Option 3: Edit the offending source code directly in the mx.* directory ……..WAIT!
Patching the framework • We (and you) do not want a lot of “one offs” of the framework floating around • Your going to want to manage your changes with patches 1. Keep track of your patches so that integrating with future drops of the framework is easy 2. Submit your patch code back to Adobe via the bugbase • Patch Management Software • Manages diffs of code so that modifications can be tracked and conflicts resolved when the source code changes • Using your framework patches (risky business): • Edit the source code directly – newer source files take precedence over older source files • Can rebuild the framework with your patches to produce a whole new framework.swc • We provide Ant tasks in {FB}/sdks/3.0.0/frameworks to do so: ant clean main
Conclusion • Flex offers developers plenty of ways to customize application and component development • Go beyond the obvious! • Read framework code – question why we do what we do! • Flex BootCamp: Wednesday 9 -12 Slides, codes, thoughts up on my blog: http://www.iamdeepa.com/blog
Q & A Slides, code, thoughts on my blog: http://www.iamdeepa.com/blog Thanks.