I've a problem, I'm using an AdvancedDataGrid .
It loads about 3000 records with about 20 columns. I constantly get Flex execution timeout because the grid executes a lot inside LayoutManager.
How can I make it asyncronousely or faster at all?
Use Datagrid pagination.
http://gurufaction.blogspot.com/2007/02/flex-datagrid-paging-example-with.html
http://stackoverflow.com/questions/1893350/how-does-flex-3-datagrid-paging-work
or something like this
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="InitApp()" xmlns:MyComp="*">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.ItemClickEvent;
[Bindable]
public var myData:ArrayCollection = new ArrayCollection();
public var orgData:ArrayCollection = new ArrayCollection();
[Bindable]
public var nav:ArrayCollection = new ArrayCollection();
private var index:int = 0;
private var page:int = 25;
private var paging:Boolean = true;
private function InitApp():void {
for( var x:uint = 1; x <= 500; x++ ) {
var obj:Object = new Object();
obj.Id = x.toString();
obj.Name = "Column " + x.toString();
obj.Street = "5555 Street";
obj.Title = "CEO";
obj.City = "El Paso";
orgData.addItem(obj);
}
refreshDataProvider(0);
}
private function navPage(d:int):void {
index += d;
refreshDataProvider(index);
}
private function refreshDataProvider(start:int):void {
if (paging == true) {
page = 25;
myData = new ArrayCollection(orgData.source.slice(start,start+page));
}
else {
index = 0;
page = 500;
myData = new ArrayCollection(orgData.source);
}
down.enabled = index > 0;
up.enabled = index + page < orgData.length;
lbl.text = index.toString() + ' to ' + (index + page).toString() + ' of ' + orgData.length;
}
private function togglePaging():void {
paging = !paging;
toggle.label = paging.toString();
refreshDataProvider(index);
}
]]>
</mx:Script>
<mx:DataGrid id="dg" dataProvider="{myData}" width="510" height="202"></mx:DataGrid>
<mx:Button x="10" y="210" label="<" click="navPage(-25);" id="down"/>
<mx:Button x="216" y="210" label=">" click="navPage(25);" id="up"/>
<mx:Label x="58" y="212" text="page" width="150" id="lbl"/>
<mx:Button x="264" y="210" label="true" id="toggle" click="togglePaging();"/>
</mx:Application>
Load the data a chunk at a time? Say slightly more than however many rows are shown visually. That way you get the perceived performance that it renders quickly.
3000 records is a lot to be loading in one go it has to be said...
Related
I am developing mobile application for iOS and Android using Flex Mobile. On one of the views I am displaying StageWebView with a Google map and a spark List control to display another data. I am using the StageWebView in order to benefit from Google Maps JavaScript API v3. Example code below:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="Clubs" backgroundAlpha="0"
viewActivate="view1_viewActivateHandler(event)"
backKeyPressed="view1_backKeyPressedHandler(event)"
initialize="view1_initializeHandler(event)">
<fx:Script>
<![CDATA[
import flash.sensors.Geolocation;
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
import spark.events.ViewNavigatorEvent;
private var myWebView:StageWebView;
[Bindable]
private var locations:ArrayCollection;
private var geolocation:Geolocation;
protected function view1_initializeHandler(event:FlexEvent):void
{
myWebView = new StageWebView();
myWebView.stage = this.stage;
}
protected function view1_viewActivateHandler(event:ViewNavigatorEvent):void
{
if(Geolocation.isSupported)
{
geolocation = new Geolocation();
geolocation.addEventListener(GeolocationEvent.UPDATE, onGeolocationChange);
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (myWebView) {
var point:Point = (new Point());
point = localToGlobal(point);
myWebView.viewPort = new Rectangle(point.x,point.y, stage.width,stage.height/3);
}
}
protected function view1_backKeyPressedHandler(event:Event):void
{
if (myWebView)
{
myWebView.viewPort = null;
myWebView = null;
}
navigator.popView();
}
protected function onGeolocationChange(event:GeolocationEvent):void
{
geolocation.removeEventListener(GeolocationEvent.UPDATE, onGeolocationChange);
locations = new ArrayCollection();
var location0:Object = new Object();
location0.lat = event.latitude;
location0.long = event.longitude;
locations.addItem(location0);
var location1:Object = new Object();
location1.lat = "42.697325";
location1.long = "23.315364";
locations.addItem(location1);
var location2:Object = new Object();
location2.lat = "42.696441";
location2.long = "23.321028";
locations.addItem(location2);
var url:String = "http://whozzzin.dev.mediatecture.at/gmapsformobile/map.php";
var counter:Number = 1;
for each(var location:Object in locations)
{
if(counter == 1)
{
url += "?locations["+counter.toString()+"][lat] = " + location.lat;
url += "&locations["+counter.toString()+"][long] = " + location.long;
}
else
{
url += "&locations["+counter.toString()+"][lat] = " + location.lat;
url += "&locations["+counter.toString()+"][long] = " + location.long;
}
counter++;
}
myWebView.loadURL(url);
}
]]>
</fx:Script>
<s:navigationContent>
<s:Button includeInLayout="{Capabilities.version.indexOf('IOS') > -1}" visible="{Capabilities.version.indexOf('IOS') > -1}" id="backButton" label="BACK" click="view1_backKeyPressedHandler(event)"/>
</s:navigationContent>
<s:List width="100%" contentBackgroundAlpha="0" id="placesList" dataProvider="{locations}" labelField="lat">
<s:layout>
<s:TileLayout columnWidth="{(width - 16)/3}"/>
</s:layout>
</s:List>
</s:View>
Currently the list is not visible because it appears behind the StageWebView. My question is how to position the List control exactly after the WebStageView.
You can use the top constraint:
<s:List width="100%" top="{stage.height/3}" id="placesList"
Edit: Put in a trace(stage.height); in your updateDisplayList function and also look at stage.stageHeight. Those values should help you figure out the exact top value to use in this case.
How I solved it:
I get the bottom of the WebStageView and convert a new point from global to local with x =0 and y = myWebView.bootom:
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (myWebView) {
var point:Point = (new Point(0,this.radiusDropDown.height));
point = localToGlobal(point);
myWebView.viewPort = new Rectangle(point.x,point.y, stage.width,stage.height/3);
this.placesList.y = globalToLocal(new Point(0,myWebView.viewPort.bottom)).y;
}
}
I am trying to bind data within a ArrayList to a list, but here only the last element shows up on the list(99), not the entire contents of the arraylist.
private function completeHandler(event:Event):void
{
var xmlData:XML = XML(event.target.data);
trace(xmlData);
var i:int = 0;
for (i;i<100;i++)
{
var arr:ArrayList = new ArrayList();
arr.addItem(i);
trace(arr);
}
list.dataProvider = arr;
}
I am not able to figure out what to do here?
You're creating an ArrayList with one item a 100 times. Replace with this and you should be fine:
var arr:ArrayList = new ArrayList();
for (var i:int = 0; i<100; i++) {
arr.addItem(i);
}
Or better yet, just wrap your XML in an XMLListCollection instead of copying the nodes one by one (assuming it is the actual content of the XML data you want instead of the indices):
private function completeHandler(event:Event):void
{
var xmlData:XML = XML(event.target.data);
list.dataProvider = new XMLListCollection(xmlData.children());
}
(Note that this is not DataBinding: it is just setting the dataProvider property)
check this code this will help you,
you can navigate through all data on the basis of rowcount of list....
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" minWidth="955" minHeight="600">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]private var _index:int = 0;
private var _coll:ArrayCollection = new ArrayCollection([{name:'ashish',age:'28'},{name:'abhi',age:'29'},{name:'kunal',age:'27'},
{name:'ashish1',age:'28'},{name:'abhi1',age:'29'},{name:'kunal1',age:'27'},
{name:'ashish2',age:'28'},{name:'abhi2',age:'29'},{name:'kunal2',age:'27'},
{name:'ashish3',age:'28'},{name:'abhi3',age:'29'},{name:'kunal3',age:'27'}]);
protected function button1_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
if((_index-li.rowCount>=0))
_index = _index - li.rowCount;
}
protected function button2_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
if((_index+li.rowCount<_coll.length))
_index = _index + li.rowCount;
}
]]>
</mx:Script>
<mx:List id="li" dataProvider="{_coll.source.slice(_index,(_index+li.rowCount))}" labelField="name" rowCount="3" width="100"/>
<mx:HBox>
<mx:Button label="<-" click="button1_clickHandler(event)"/>
<mx:Button label="->" click="button2_clickHandler(event)"/>
</mx:HBox>
</mx:Application>
I'm somewhere between novice and intermediate levels with Flex and brand new to Flex 4. I've built a magazine app for a client that pulls in dynamic issue information and generates a book using the qs FlexBook component. The problem is that the app seems to take forever to BEGIN loading.
The app progress bar does not display for several seconds. Once it finally shows up, the app loads quickly. The file sizes don't seem overly large to me and the issue remains whether I use RSLs, merge the code or convert it to a module. You can see the effect here: http://whosthatnerd.com/clients/jones/issues/
Here is my MXML file:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
preloader="mx.preloaders.DownloadProgressBar"
skinClass="skins.TransparentAppSkin"
creationComplete="init()"
minWidth="955"
minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/mx";
#namespace qsctrl "qs.controls.*";
qsctrl|FlexBook {
hardbackCovers: false;
paddingTop: 0;
paddingRight: 0;
paddingBottom: 0;
paddingLeft: 0;
paddingSpine: 0;
color: #000000;
textRollOverColor: #000000;
edgeAndCornerSize: 70;
background-color: #000000;
}
mx|HBox {
paddingTop: 0;
paddingBottom: 0;
paddingLeft: 0;
paddingRight: 0;
horizontalGap: 0;
}
mx|Image {
padding: 0;
margin: 0;
}
mx|ProgressBar {
color: #EEEEEE;
}
</fx:Style>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.containers.HBox;
import mx.controls.Alert;
import mx.controls.Image;
import mx.core.IUIComponent;
import mx.core.UIComponent;
import mx.events.ResizeEvent;
import qs.controls.FlexBook;
private var issueID:String;
private var xmlLoader:URLLoader;
private var xml:XML;
private var swfLoader:Loader;
private var swfClass:Class;
private var book:FlexBook;
public var pageHeight:int = 890;
public var pageWidth:int = 600;
private function init():void {
loadingIndicator.x = appCanvas.width / 2 - loadingIndicator.width / 2;
loadingIndicator.y = appCanvas.height / 2 - loadingIndicator.height / 2;
issueID = parameters.issue_id;
xmlLoader = new URLLoader();
xmlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
xmlLoader.addEventListener(Event.COMPLETE, fillBook);
xmlLoader.load(new URLRequest('/clients/jones/issues/issues/view/'+issueID+'.xml'));
}
public function progressHandler(e:ProgressEvent):void {
loadingIndicator.setProgress(e.bytesLoaded, e.bytesTotal);
loadingIndicator.label = 'Loading Publication... '+Math.round(e.bytesLoaded / e.bytesTotal * 100).toString();
}
private function scaleBook(e:* = null):void {
book.height = Math.ceil((appCanvas.height * 0.9));
book.width = Math.floor((book.height * 1.491285403050109));
book.y = appCanvas.height / 2 - book.height / 2;
book.x = appCanvas.width / 2 - book.width / 2;
}
private function fillBook(e:Event):void {
xml = new XML(e.target.data);
if(xml.use_swf == 1) {
trace('loading: '+xml.swf);
swfLoader = new Loader();
swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, useExternalSwf);
swfLoader.load(new URLRequest(xml.swf));
} else {
usePageImages(xml);
}
publicationName.text = xml.publication.name;
var d:Array = String(xml.pub_date).split('-');
issueDate.text = 'Published: '+d[1]+'/'+d[2]+'/'+d[0];
}
public function prepareDisplay():void {
loadingIndicator.visible = false;
bookDetails.x = book.x;
bookDetails.y = book.y;
bookDetails.width = book.width / 2;
bookDetails.height = book.height;
bookDetails.visible = true;
}
public function usePageImages(xml:XML):void {
book = new FlexBook();
book.itemSize = 'halfPage';
scaleBook();
var box:HBox;
var img:Image;
var pages:Array = new Array();
for(var i:int = 0; i < xml.page.length(); i++) {
trace(i);
trace(xml.page[i].image_url);
box = new HBox();
box.horizontalScrollPolicy = 'off';
box.verticalScrollPolicy = 'off';
img = new Image();
img.maintainAspectRatio = true;
img.percentHeight = 100;
img.percentWidth = 100;
img.source = xml.page[i].image_url;
box.addChild(img);
if(i == 0) {
book.cover = box;
} else if(i+1 == xml.page.length()) {
book.backCover = box;
} else {
book.addChild(box);
pages.push(box);
}
}
book.content = pages;
appCanvas.addElement(book);
prepareDisplay();
appCanvas.addEventListener(ResizeEvent.RESIZE, scaleBook);
}
public function useExternalSwf(e:Event):void {
trace('LOADED SWF');
book = new FlexBook();
book.itemSize = 'halfPage';
scaleBook();
var mc:MovieClip = MovieClip(swfLoader.content);
swfClass = mc.constructor;
var dupe:MovieClip;
var comp:UIComponent;
var box:HBox;
var pages:Array = new Array();
for(var i:int = 0; i < mc.totalFrames; i++) {
dupe = MovieClip(new mc.constructor);
dupe.gotoAndStop(i);
comp = new UIComponent();
comp.addChild(dupe);
box = new HBox();
box.addChild(comp);
box.horizontalScrollPolicy = 'off';
box.verticalScrollPolicy = 'off';
dupe.width = comp.width = book.width / 2;
dupe.height = comp.height = book.height;
if(i == 0) {
book.cover = box;
} else if(i+1 == xml.page.length()) {
book.backCover = box;
} else {
book.addChild(box);
pages.push(box);
}
}
book.content = pages;
appCanvas.addElement(book);
prepareDisplay();
appCanvas.addEventListener(ResizeEvent.RESIZE, scaleBook);
}
]]>
</fx:Script>
<s:BorderContainer id="bookDetails" visible="false">
<s:backgroundFill>
<s:LinearGradient>
<s:entries>
<s:GradientEntry color="0x707070" ratio="0.00" alpha="1" />
<s:GradientEntry color="0x505050" ratio="0.75" alpha="1" />
</s:entries>
</s:LinearGradient>
</s:backgroundFill>
<s:borderStroke>
<s:SolidColorStroke joints="miter" color="0x101010" weight="12" />
</s:borderStroke>
<s:layout>
<s:VerticalLayout paddingTop="18" paddingRight="18" paddingBottom="18" paddingLeft="18" />
</s:layout>
<s:Label id="publicationName" fontSize="32" fontWeight="bold" color="0xEEEEEE" alpha="1" />
<mx:Text id="issueDate" fontSize="20" color="0xEEEEEE" alpha="1" />
<mx:Text id="bookInstructions" fontSize="20" color="0xEEEEEE" alpha="1" text="Click or drag the corners to turn the page." />
</s:BorderContainer>
<s:BorderContainer id="appCanvas" left="0" right="0" top="0" bottom="0" skinClass="skins.TransparentAppSkin"></s:BorderContainer>
<mx:ProgressBar id="loadingIndicator" label="Loading Publication..."/>
</s:Application>
I honestly don't know if the issue is my player or my code. Thanks in advance for your help :)
I have recently figured out how to use an SQLite db with Flex. Now I'm having trouble displaying the data properly. I've tried several binding strategies and I've largely come up short. I had undefined property errors, unusable errors, and finally! Code without errors! Also, code without a displayed image. Any help is appreciated as always.
Here's my code so far; trying to keep it tidy, Async, and I've left an unused variable or two from my messing around with it. Thanks for any insight.
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
title="NM1"
>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import flash.data.SQLConnection;
import flash.data.SQLResult;
import flash.data.SQLStatement;
import flash.filesystem.File;
import mx.collections.ArrayCollection;
private var conn:SQLConnection;
private var createStmt:SQLStatement;
private var selectStmt:SQLStatement;
[bindable] private var dataField:ArrayCollection;
[bindable] private var row:Object;
[bindable] private var pngIndex:int;
[bindable] public var pngTitle:String;
[bindable] private var pngByteArray:ByteArray;
private function init():void
{
conn = new SQLConnection();
conn.addEventListener (SQLEvent.OPEN, openSuccess);
conn.addEventListener (SQLErrorEvent.ERROR, openFailure);
var dbFile:File = File.applicationDirectory.resolvePath("assets/NM.sqlite");
conn.openAsync(dbFile);
}
private function openSuccess(event:SQLEvent):void
{
conn.removeEventListener(SQLEvent.OPEN, openSuccess);
conn.removeEventListener(SQLErrorEvent.ERROR, openFailure);
getData();
}
private function openFailure(event:SQLErrorEvent):void
{
conn.removeEventListener(SQLEvent.OPEN, openSuccess);
conn.removeEventListener(SQLErrorEvent.ERROR, openFailure);
// Make an alert Dialog
// = "Error opening database";
trace("event.error.message:", event.error.message);
trace("event.error.details:", event.error.details);
}
private function getData():void
{
//status = "Loading data";
selectStmt = new SQLStatement();
selectStmt.sqlConnection = conn;
var sql:String = "SELECT Picture FROM Data WHERE 'Index' = 0";
selectStmt.text = sql;
selectStmt.addEventListener(SQLEvent.RESULT, selectResult);
selectStmt.addEventListener(SQLErrorEvent.ERROR, selectError);
selectStmt.execute();
}
private function selectResult(event:SQLEvent):void
{
//status = "Data loaded";
selectStmt.removeEventListener(SQLEvent.RESULT, selectResult);
selectStmt.removeEventListener(SQLErrorEvent.ERROR, selectError);
var result:SQLResult = selectStmt.getResult();
// dataField = new ArrayCollection(selectStmt.getResult().data);
if (result.data != null) {
row = result.data[0];
pngIndex = result.data[0].Index;
pngTitle = result.data[0].Title;
pngByteArray = result.data[0].Picture;
Pic.source = pngByteArray;
}
}
private function selectError(event:SQLErrorEvent):void
{
//status = "Error loading data";
selectStmt.removeEventListener(SQLEvent.RESULT, selectResult);
selectStmt.removeEventListener(SQLErrorEvent.ERROR, selectError);
trace("SELECT error:", event.error);
trace("event.error.message:", event.error.message);
trace("event.error.details:", event.error.details);
}
]]>
</fx:Script>
<s:Image id="Pic" x="0" y="0" width="263" height="99"/>
<s:TextArea id="text1" x="0" y="313"
/>
EDIT I have updated the code now, with perfect, error-free code that does not display my image. Help!!
Make sure you call the first function in the initialize() function as your program starts!
I had forgotten it somewhere in my code testing. :/
<fx:Script>
<![CDATA[
import mx.controls.*;
import mx.controls.TextInput;
import mx.events.ListEvent;
public function init():void
{
for(var i:int=0;i<5;i++)
{
var txtbox:TextInput = new TextInput();
txtbox.id = "text"+i;
myHBox.addChild(txtbox);
}
}
public function getVal():void
{
}
]]>
</fx:Script>
<mx:HBox id="myHBox" width="100%" height="100%">
<mx:Button label="Get Value" click="getVal()"/>
</mx:HBox>
I have implemented this one. I am getting 5 textboxes with empty value, if i entered some value in each textbox then, i want to get specific 3rd textbox value wen some event trigger. so how i can i make. since am new to flex. Pls give me solutions. Thanks in advance.
Why don't you just store the values in its own data structure?
<fx:Script>
<![CDATA[
import mx.controls.*;
import mx.controls.TextInput;
import mx.events.ListEvent;
private var inputs:Vector.<TextInput> = new Vector.<TextInput>();
public function init():void
{
for(var i:uint = 0; i<5; i++)
{
var txtbox:TextInput = new TextInput();
inputs.push(txtbox);
myHBox.addChild(txtbox);
}
}
public function getVal():void
{
var value:String;
for(var i:uint = 0, len:uint = inputs.length; i<len; i++)
{
value += inputs[i].text + ' ';
}
trace(value);
}
]]>
</fx:Script>
<mx:HBox id="myHBox" width="100%" height="100%">
<mx:Button label="Get Value" click="getVal()"/>
</mx:HBox>
Also, if this is a new project, why are you using Flex 3?
Your question is not all too clear, but if I understand correctly,
Try this:
public function init():void
{
for(var i:int=0;i<5;i++)
{
var txtbox:TextInput = new TextInput();
//txtbox.id = "text"+i;
txtbox.name = "text"+i;
txtbox.addEventListener(Event.CHANGE,onChange);
myHBox.addChild(txtbox);
}
}
private function onChange(event:Event):void{
Alert.show(TextInput(event.target).text,TextInput(event.target).name + " Changed");
}
public function getVal():void
{
Alert.show(TextInput(myHBox.getChildByName("text3")).text,"Value");
}
cheers