This is a general question on optimization technique and please I am more than willing to rewrite a majority of my code as I am moving a lot of it to a library.
My concern applies not so much to flex performance as I have used methods that have reduced cpu/memory footprint so performance is quick when inside a view.
The problem I have is with the navigator.pushView which seems slow, I do call my init function on creationComplete for the view but I have it factored so my init looks like:
private function init() : void {
doStuff1();
doStuff2();
doStuff3();
}
What can I do to make the view transition smooth? This is on a mobile device.
I have considered delaying off all of the code inside the init function using a timer so that for lets say the first 3 seconds there is nothing happening and the view has all the frames it needs but that doesn't seem right.
Advice would be much appreciated!
Thank you,
Performance really depends on what you're doing in those "doStuff()" methods. A few things to consider:
1) At the time creationComplete() executes; the view has already rendered once. Are you doing anything that will cause the thing to render itself again? Changing styles, and many properties on children components will cause that child to re-render and often the view component.
A lot of people use creationComplete as a constructor when, in reality, that is the worst place to put "constructor style" code. Instead you should consider using preinitialize for most stuff, or initialize if you need to set properties on children components.
2) viewActivate executes after the transition occurs. So, perhaps you should consider moving code out of creationComplete and into viewActivate. More info on a mobile view's lifecycle is here.
Have a rather bizarre issue with Flex throwing an error when teh application is running in the background. I use Selenium and SeleniumFlexApi to run various tests against my app. If the browser window is in the foreground or any part of it is visible to teh screen, the test pass as expected. However, if the window is in the background and not visible, I am getting the following error in 1 part of my app.
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
I have a VBOX that creates a number of children and then upon creationComplete(or UpdateComplete, I've tried both) it then needs to remove any of the children that are not visible. Each child has a listener for CreationComplete which checks if the child is visible and if not, adds it to an array which is iterated over when the parent UpdateComplete is fired. I cant seem to find any reason for this behavior and am curious if its an issue with the Flex Component LifeCycle.
The most recent version of the Flash Player (10.1) will automatically "slow down" when minimized. I think it drops to a couple of frames a minute [as opposed to the standard 24 per second for Flex]. I don't know specific number.s This is for performance and 'battery life' reasons.
If there is anything in your app, or in your testing, that requires specific timing or uses a timer, then this will easily break unit tests.
I've heard from other folks that this have other folks that have had issues with this. The best solution I've heard proposed is "Add a flag to turn this off; even if it's only in the debug player." But, there is no solution right now other than "run your tests w/o the app minimized"
I have a timer event that updates certain things in my app (from a PHP Service) every 5 seconds. Every time this timer ticks, it makes the cursor blink to a clock and then back to the arrow. Since this is happening every 5 seconds, it gets pretty annoying. Is there a way for me to prevent the cursor from changing when the timer ticks?
UPDATE: I've figured out a work-around by setting a custom cursor with high priority (I just made a .png with a cursor in it). This works, but the cursor doesn't seem to move as smoothly as normal. Anyone know of a better solution?
I'm repeating my comment as an answer since it solved your issue, and adding a bit of detail. When you use the Data Connection wizard the default flag for showBusyCursor is "true" in order to prevent it you need to change this setting to "false".
I'm not sure what the FB4 wizard builds since I'm still using FB3, but if it's similar to the mxml httpService you just need to find the service in the .mxml file and you will see that attribute.
Now repeat after me. "All programmers make silly mistakes, especially when we are using new languages, I am no more of a moron than any other programmer" If, in a year, you look back on your code and don't say to yourself "what was I thinking" then you're probably doing something wrong.
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
Is there a way to force a JavaFX app to repaint itself before proceeding? Similar to a Swing Panel's paint(Graphic g) method (I might be getting the keywords wrong there).
Consider the following example: you write a TicTacToe app along with the AI required for a computer player. You would like the ability to show two computer players duke it out. Maybe you put in a two second pause between computer turns to give it a life-like affect. When you hit your "Go" button, there's a large pause of unresponsiveness (the time it takes for the 9 turns to go by with faked pauses for the computer to 'decide') and then suddenly the app's visual is updated in with the completed game's state.
It seems like JavaFX repaints once processing in the app's thread is finished? I'm not completely sure here.
Thanks!
You are right. JavaFX is event-driven and single-threaded. This means that repaint and event response can not be done simultaneously. Long-running task should be executed on separate thread so they do not block the rendering of the UI, When the task is finished it can sync back to the FX thread by calling FX.deferAction() which will simply execute the code on the main thread.
This won't be the most helpful answer as I have toyed around with JavaFX for all of half a day, but wouldn't you use Timelines, Keyframes, and binding to accomplish your repaints instead of calling them explicitly like you have described?
See this tutorial for an example.
JavaFX's model is to separate you from the painting of the "stuff" on the screen. This is very powerful but is a change from how you might be familiar with.
whaley is correct that the appropriate way of doing this in JavaFX is to make a timeline where the move is done every X seconds and will be drawn at that keyframe.
If you have a question about how to do this, try it and make a new question with some code.