In Flex, What is the difference between a skin and an itemRenderer? - apache-flex

Indeed they both (skins and itemRenderers) seem to do drawing using the flash.graphics.* package. I have copy pasted code between skins and itemRenderers before, so I really don't understand the difference. I have had more experience implementing itemRenderers than skins, so that might be part of the problem. Thanks, let me know.

A skin is a graphical element that can be applied to various UIComponents. Containers can have borderSkins and Buttons can have various up/over/down skins. They can be implemented in several ways, including the use of the drawing API ("Programmatic skins") or through embedding assets ("Graphical skins"). Skins are usually pretty lightweight and may only be a Flash DisplayObject rather than a Flex UIComponent, which is more heavyweight but contains much more functionality.
An itemRenderer is typically a UIComponent that a List-based control uses to display an item. You also usually use itemRenderers when using a DataGrid/DataGridColumn. Most components that use itemRenderers recycle them, meaning that they create about as many as are needed to display on the screen, and as the user scrolls through the data the same itemRenderers are repositioned and get new data plugged into them. This is one of the reason why Lists and DataGrid can support large quantities of data and why trying to accomplish similar things with a Repeater leads to apps with terrible performance.

Related

Flex: Is it a good idea or design to include an MXML another MXML file?

I want to know if its a good idea to have an mxml file for each component, then inline these various components in one mxml file and able to communicate between these mxml files ?
For example I have a overView.mxml and in this, i inline the other mxml files which contains components like datagrid, another mxml contains may be a form. Will i be able to communicate to the grid data by accessing its id in the form mxml ?
Please let me know if my question is not clear. I will try to rephrase it.
Thanks so much.
Yes, this is a good idea. It's much better than creating one giant MXML or class that contains all of your functionality.
At the same time, it caries some overhead. To communicate between the classes (MXML files are just classes) you have to dispatch events. A parent component that contains child components, can set public properties of its child components (with or without data binding).
You should try to decouple your components as much as possible. Try not to write code where the child component is explicitly referring to the parent (ie: try not to use the parent property). Instead dispatch an event from the child component and make the parent listen for the event.
Regarding your example with a data grid and a form:
If these two objects will have a lot of interaction between them, it will be much easier to keep them in the same MXML file. This doesn't sound like a scenario where one is a parent component that contains a child component. Since these "siblings" are likely to communicate w/each other, it would be easier to have them in the same MXML file. However, if things get complex and the file grows to more than a couple hundred lines, you will likely benefit from separating them.
Let's say you plan to use the form component elsewhere in your project w/out the data grid, then it also makes sense to separate them.
Regarding your question: "will the form component be able to communicate w/the grid component by accessing it's id?":
Technically, yes, you could do that but only by tightly coupling your form component w/the grid component. The form component can use the parent property to go up one level and use the id of the grid. But since the parent property is typed as a DisplayObjectContainer you have to fool the compiler and you loose the benefits of strong typing (because the DisplayObjectContainer doesn't have a property that is the ID of your grid). So while this is possible, it's not good design and prevents you from reusing the form component elsewhere.
This tight coupling defeats the purpose of creating separate components. So you're back to either facilitating that communication through dispatching events, or putting the grid and form in the same document :)
TLDR:
You should generally be trying to create re-usable components. So I would generally lean in that direction. MXML files are just classes, all the usual things people talk about in object oriented programming apply.

skin the dropdownbox

i am wondering if there is a way to skin the whole drop down box, after searching Google i could only find thing like adding icons resizing and alike, but no full skinning of the box.
Is this at all possible and if so how? i would very much like my whole program to be skinned rather than everything but the drop down boxes.
I am more of a designer than a coder so as far as code goes I'm quite a novice with the code side, would be a great help if you could give me a point in the right direction and/or a quick insight how to do it.
in flex... sorry
Thanks.
i am wondering if there is a way to skin the whole drop down box,
Yes, create a custom skin class for the DropDownList, just like you would any other Spark class. You can use code for the DropDownListSkin as a reference point for creating your own. In Flash Builder, if you create a new MXML Skin; and specify the hostComponent as a DropDownList then you'll get the DropDownListSkin code as a starter point for your customization.
For more info, read these docs on skinning Spark Components.
We did, in essence, exactly this to create our Mobile DropDownList.

Need to "introspect" innards of flex <mx:itemRenderer>

I've got a flex app with a DataGrid with several columns (defined in the MXML file), and I need to "introspect" the grid columns. That is, I need to write some ActionScript code which, given the DataGrid object, can determine various things about the grid (and more specifically, the columns of the grid).
In particular, if a column is just plain text output, I don't really care about it... but if it's got "actionable" controls within it (checkboxes, linkbuttons, etc) I do.
First, I'm assuming that columns which contain "actionable" contents will be within <mx:itemRenderer> tags (else it would just be plain text); please let me know if this is incorrect.
Next I need to "dig down" into the structures, pulling the AS object corresponding to the <mx:DataGridColumn> out of the <mx:DataGrid> (I've got this), then pulling the AS object corresponding to the <mx:itemRenderer> out of the mx:DataGridColumn (two diff ways to do this; neither seems very useful), then pulling the AS object that corresponds to the <mx:Component> out of the mx:itemRenderer (if any; it's unclear to me whether the mx:Component actually creates an object), and finally pulling the AS object corresponding to the <mx:LinkButton> (or whatever) out of the mx:Component.
Does anyone know how to do this?
P.S. I understand that there's almost no limit to what could be lurking within the itemRenderer; if I can dig down that far, I'm willing to test for a handful of things that I expect and ignore the rest.
To clarify somewhat, I've been asked to provide Section 508 compliance (accessibility) to an existing application. There are a lot of pieces to this, of course, including screen readers, etc... but one of the first steps is making sure that the application can be used without a mouse.
Many of the existing screens have a UI technique consisting of a DataGrid with item renders which place controls like radio buttons and linkbuttons and whatnot into the cells (same type of control all the way down the column). All well and good, except I can find no way to interact with these controls via the keyboard.
So, I modified one screen to have a hot key which pops up a context menu, allowing the user to arrow up/down among the actionable items, and press ENTER to choose one (toggle the checkbox, press the linkbutton, etc). But this was screen-specific, and it will be too easy for someone to update the screen (e.g. adding another actionable column) and neglect the menu.
A better (?) approach was suggested: subclass the data grid, introspect to find the actionable columns, build the menu automatically, and now all we have to do is swap out the SuperDataGrid for the DataGrid, and our screens will be 508 compliant.
If someone can recommend a better way to make the screens 508-compliant (without redesigning the UI) and with minimal per-screen effort, I'm all ears.
Maybe I'm not being clear enough, since you keep missing the point, so let me try again.
I'm NOT writing application-level code... if I were, I'd know exactly what the logic is doing and I'd be able to use the bound data in the normal way. In fact, the application-level code DOES use the bound data in the normal way. But that's totally beside the point.
What I'm TRYING to do is write "infrastructure-level" code: that is, code which runs "below" the level of the application logic. I'm trying to effectively add a feature to DataGrids which Adobe should have included, but didn't. If I can get this class working, it will be possible to just drop it into dozens of screens WITHOUT ME, AS THE CLASS AUTHOR, KNOWING ANYTHING ABOUT THOSE SCREENS OR THE LOGIC WITHIN THEM. The only way I can imagine this working is to look into the datagrid and discover, at run time, what types of controls lurk within it, and possibly what they're bound to (actually, I can probably just execute whatever the click="foo()" attribute says to do, and I won't need to know what they're bound to).
Does this make sense?
Is it possible?
Item renders interact with the outside world through their data property. They should render the data as desired and make changes to data as required. They should not reach outside and you should not try to reach in to affect an item renderer directly.
As far as the underlying problem you're trying to solve, you haven't stated it at all. You're describing a desire to follow through on a particular solution only but haven't described the underlying problem. What are you really trying to accomplish? Don't talk about getting access to item renders or digging into the DataGrid, but what interaction or affect on the rows do you want? The problem is your approach is somewhat backwards and that's why it's not working out.

when should I override 1 of the lifecycle methods?

I've read in the flex developer guide that you sometimes need to override one
of the lifecycle methods like: commitProperties and updateDisplayList
but I've written a few flex apps without ever needing to implement them.
when do I need to override them?
First, I 100% recommend studying this presentation by EffectiveUI:
Diving Deep with the Flex Component Lifecycle
and this by Michael Labriola from Digital Primates:
Diving in the Data Binding Waters
They go into things you'll never find in the docs but that are super practical for understanding the Flex Component Lifecycle.
From my experience, the only time you need to worry about overriding core lifecycle methods is if you are creating components. I make a distinction between Application Views and the Components.
Components are things that need to be nearly perfect, highly optimized, and extremely versatile/abstract.
Views are things that you may only need in one Application, but could reuse if you so desired (LoginScreen, ContactForm, etc.).
Views, for the most part, are just adding things to the display list of a more generic component (Canvas, Group, Container, VBox, List, etc.). You, as a View/Application developer, don't really care about how the "dataProvider" creates it's itemRenderers, it just works.
Components are a different story though. When you create a component, you want it to fit perfectly into that system Flex has set up: the Component Lifecycle. It's pretty tough when you first try to build a component like they do, but after you wrap your head around it it's super easy. Here's how I think of the methods when I develop components:
createChildren()
Called once when component is constructed
Called top down. So if Panel calls createChildren, it's createChildren method will call addChild on all of it's children, which calls initialize, which calls createChildren.
If you created a custom component, say a StarRatingComponent, you might want to add 5 stars to the stage when the component is constructed. So you'd override createChildren() to do add stars to the component you're in. By default, though, all Container components in the Flex SDK add their children here (lists do it a bit differently), so you never have to do this if you're building MXML views or something not-to-be-extremeley-reusable.
The next 3 methods are called 1 frame after properties are set.
measure()
If the parent doesn't have any sizing (percent or explicit), it will need to be sized based on it's children's sizes. This can only happen from the bottom up (took me quite a while to really wrap my head around that).
If the parent has explicit or percent sizes, it skips this step.
You override measure if you want to:
Have measuredWidth or measuredHeight return a useful value. So if you build a custom CoverFlowContainer component, and measuredWidth/measuredHeight aren't set (because measure was not overriden), then if you don't specify any sizing on CoverFlowContainer, it would be 0 width 0 height. So instead, override measure and have it set measuredWidth to radius * 2 or something like that, and now you don't need to give it a size!
If the component does not have an explicit or percent size, measure will be used to size the component. Otherwise it's skipped.
commitProperties
Called after measure.
Applies all property changes (from setting properties on the component) to the component (they were stored in private variables for that first frame).
Called a frame after initial property settings.
This is the most important method to override in my opinion. So for your CoverFlowContainer, say you set the hypothetical distance, gap, selectedItem, and tilt properties. When you set them, store them in private variables. Flex will wait a frame, and call commitProperties. In your overridden commitProperties, you can then say layout.updateEverything(selectedItem, distance, gap, tilt); so to speak. So this is the method you override to make all property changes be applied at once.
updateDisplayList
Called after commitProperties
Called top down.
You only override this to set visible properties on the component, such as setActualSize, graphics, etc. But by now (because of `commitProperties), you have all your required variables to update the display set to the right values.
Overall
So from my experience, I worked a lot with these lifecycle methods when creating a component library for things I would use in a million projects:
TitleWindow (my own version)
View3D (for Away3D/Papervision)
Tree and Stack for Flex 4
TextArea (with prompt, expandable, etc.)
ToolTip (easier to skin tooltip)
I needed to make sure everything was updated and rendered perfectly according to the lifecycle. Reading and understanding the Flex 4 Spark Source Code really helps clarify when to override these methods. As does the Openflux Source Code (very simple, clear alternative to the Flex Framework. Not as feature rich so it shows how to bare-bone override those methods to accomplish some pretty advanced things).
When I develop applications and make things like AdvertismentView, MenuView and LoginView, I don't ever think about it because all the components I'm using have already solved those problems (ViewStack, Group, List, etc.). I'm basically just setting properties they've defined and updated in their own commitProperties override.
The only time I would start overriding lifecycle methods in a View would be when I need to access custom variables from outside the view. So say I had a custom RichTextEditor and I created some properties called showFontControls and showStylePanel. When I set those variables, I would probably do what they described in the Data Binding Presentation: accessor sets private variable and calls the invalidation methods, lifecycle methods execute a frame later and I have overridden commitProperties and updateDisplayList to show those panels and fonts. But in practice, that's probably overkill because it wouldn't offer that much of a performance gain for the amount of work it would take. I'd just set up some binding to a visible property in that case. Nevertheless....
The best thing to do to really get into this is to just download the Flex SDK Source and see what they're doing.
Hope that helps.
Lance
Here's another presentation by Deepa (from the Flex framework team) that goes over a lot of the same framework methods, including a nice explanation of why the whole invalidation model exists to begin with:
http://tv.adobe.com/watch/max-2008-develop/creating-new-components-in-flex-3-by-deepa-subramaniam/

Flex app with large number of UI objects == slow?

I'm building my first Flex custom component, in Flex 3. It is a data table based on the 'Grid' container class, with a simple text Label in each cell. (DataGrid and AdvancedDataGrid were not appropriate starting points for my needs.) The component works quite well using smallish tables, but I tried stress-testing it using a larger table, and have been disappointed by the results.
The component creation process has some slow spots, but those are in my power to optimize and aren't my primary concern. What worry me more are what appear to be limitations in the Flex framework itself.
This 'large' sample table has a bit over 7000 cells in it. This is largish, but still 1-2 orders of magnitude less than the biggest I need to accommodate. In standard Grid structure, the main portion of the component consists of a Grid with 400 GridRows of 16 GridItems each, plus a few other smaller ancillary Grids.
Once the table renders, I find the following:
Mouse-related events are slow to fire. Specifically, I have rollOver/rollOut event handlers registered on each table cell, to let me highlight the cell under the pointer. On a small table, I could move the mouse over the table very quickly, and the highlighting would follow the pointer in real-time. With the larger table, the highlighting is very jerky, changing only about twice per second, skipping over many cells.
If I place the mouse cursor over the component and leave it there, my CPU is pegged (one processor core, anyway), and stays that way until I move off of the component, when it drops to idle. My component isn't doing anything at all at this point.
It feels like Flex simply cannot scale to support component trees that are this large. I shudder to imagine how it would behave with 100,000 cells. Perhaps I'm pushing the Grid beyond its intended use, but having an object per table cell doesn't seem like an unreasonable model, and ~14,000 objects in the tree (a GridItem and a Label per cell) seems pretty modest.
I have yet to get useful data out of the FlexBuilder profiler; I'm working on it. For now, my biggest questions are:
Am I really pushing the limits of Flex with this modest test?
Is my approach to this component completely off-base?
I'm running this on Flash Player 9 under Firefox on WinXP.
Yes, Flex is not designed to support very large numbers of components, it is well known that you should minimize the number of components and don't use features that you don't need (Eg. DisplayObject instead of Canvas if you don't need the extra functions).
It's unwise to mirror your data exactly with displayed objects. DisplayObjects (and related classes) are relatively heavyweight, and you need to control how many of those you have.
I would say that the scale you're working at, with 1000+ Cells, and an event listener for each one, would definitely reach Flex's limits.
I think you should take a better look at your approach and architecture. I assume you are not displaying all 1000+ items at the same time, perhaps you should use paging and display 100ish with each screen, with previous/next buttons to move on to another page. You could also consider dynamically adding and removing rows using a custom scrollbar, simulating the scroll effect. This is much more complicated to do.
Boy, it seems we can write a book on this topic. Or atleast a chapter. We learnt quite a few things in this area as we were developing our products.
Bottom line - yes, Flex will slow down to a halt when you add 1000+ "things" on the screen. Here are a few bullet points, and some repetitions of what's already mentioned (just to be concise)
1) Always draw only what is visible. Hans Muller, the architect on the new Spark DataGrid has a great writeup on ViewPorts. http://hansmuller-flex.blogspot.com/2009/06/introduction-to-viewports-and-scrolling.html. So instantiate enough "cells" to fill up the visible area, and basically recycle them as the user scrolls.
2) Recycle, recycle, recycle: Further to above, as the user scrolls, you obviously have to recycle cells that are now out of view to show the ones that are in view. Here there are a few things we learned the hard way :-)
-> Instead of disposing and creating new cells, either use reparenting or use repositioning (prefer repositioning)
What this means is this: Say you have a 10X10 grid (visible) showing a 100X100 data provider.When the user scrolls to cells 20X20, the quickest way will be to set the X and Y of the existing cells to the new locations, and then call set data for each. We used reparenting earlier because our scenario was a series of related containers, so this may not apply to you. But bottom line - we simply move "rows" around the visible area. So creating and destroying will be slow, removing and adding to the display object list will be faster, and just moving around (x,y) will be fastest.
3) Choose what you inherit from wisely: The Flex SDK is a beast. So choose your "cells" base class wisely. For example, the SDK DataGrids, have a lightweight renderer that inherits from UITextField (Halo), as opposed to Label. Even UIComponent will be heavy in certain scenarios. Look up the asdocs for UIComponent and see if you need everything in there, else consider inheriting from further up its hierarchy.
4) Cache Calculations: Do this last in your development cycle. Once you are done with a feature, run flex profiler. Identify the longest running methods, and the most called methods. We always do this when we release, because there's always improvements to be made. There's a lot of math involved when you're developing a highly visual component, and too many calculations will slow things down.
5) Make sure you profile for memory : Unwired event listeners, rogue object references, etc will kill performance. Flex profiler is an excellent tool to combat this, so make sure you use it.
We have some good links here:
http://www.flexicious.com/resources/Ultimate/Docs/LargeDataset.htm?
Hope this helps!
If you look at any List-based control in the Flex framework, you'll see that they make significant use of item renderers which are recycled. So a DataGrid with 20 rows displayed only creates about 22 renderers and recycles them as you scroll through the list. This is why a DataGrid can hold thousands of records and still have pretty snappy performance. I recommend you check out Peter Ent's series of articles on item renderers and take a look at ListBase/List and some of the related classes to understand how to build something similar:
http://weblogs.macromedia.com/pent/archives/2008/03/itemrenderers_p.html
Without seeing your code and knowing exactly what you're trying to do...it definitely seems like you're pushing the limits of Flex by pushing that much data into the framework all at once.
Keep in mind that the Flash runtime wasn't designed to handle huge applications...but run somewhat light applications inside the browser. It also seems unlikely that your users are going to need to have access to all of those controls all at once.
You could try providing data services (Java, .NET, etc.) to drive the data in your application. You would then page through the data so that the framework is only dealing with maybe 200 - 300+ elements at a time.
In flex, if you using Mouse move event to redraw anything .. You might have experienced very slow rendering .
eg:
this.addEventListener(MouseEvent.MOUSE_MOVE, redraw);
and
public function redraw(anything:Object=null):void{
//draw something here
this.graphics.clear();
this.graphics.lineStyle(3, 0x000000);
this.graphics.moveTo(startPoint.x, startPoint.y);
this.graphics.lineTo(endPoint.x, endPoint.y);
this.scaleTextInput.x = centerPoint.x;
this.scaleTextInput.y = centerPoint.y;
}
The Above code results very slow rendering ...
Solution:
Use Event.ENTER_FRAME event instead? Although more resource intensive than the mouse move event, you should receive considerably more updates per second, allowing the mouse to appear more responsive to the user:
Eg:
this.addEventListener(Event.ENTER_FRAME, redraw); instead of
this.addEventListener(MouseEvent.MOUSE_MOVE, redraw);
and You are good to go ..Happy Flexing
More on:
http://www.deepakdhakal.com

Resources