More on the Future of Flex & Flash

Posted: November 21st, 2011 | Author: | Filed under: Adobe, AIR, Flash, Flex, Mobile | Tags: , , , , , | No Comments »

Late last week, Adobe released official statements and a FAQ to address the recent confusion around the Flex, the Flash/AIR platforms and mobile.    You can read the official statement at:

http://www.adobe.com/devnet/flashplatform/articles/recent-updates.html

You can read the FAQ at:

http://www.adobe.com/devnet/flex/articles/flex-announcements.html

Here are a few excerpts from the official statement:

Adobe Flash Player on desktop
Adobe reaffirmed its commitment to the Adobe Flash Player in desktop browsers, and its role of enabling functionality on the web that is not otherwise possible. Flash Player 11 for PC browsers just introduced dozens of new features, including hardware accelerated 3D graphics for console-quality gaming and premium HD video with content protection.

Adobe AIR for mobile
Adobe reaffirmed its commitment to Adobe AIR for mobile devices, which allows developers and designers to create standalone applications using Adobe Flash technologies that can be deployed across mobile operating systems, including Apple iOS, Google Android and RIM BlackBerry Tablet OS.

Adobe AIR for desktop
Adobe reconfirmed its commitment for its continued support for Adobe AIR applications running on the desktop. Adobe is actively working on the next version of Adobe AIR for the desktop.

Adobe Flex
Adobe announced its intention to contribute the Adobe Flex SDK open source project to the Apache Software Foundation for future governance.


No, Flex & Flash Are Not Dead

Posted: November 16th, 2011 | Author: | Filed under: Adobe, AIR, Flash, Flex, Mobile | Tags: , , , , | 8 Comments »

Last week Adobe announced information about the company’s evolution and future plans of Flex. It was also announced that Adobe Flex would be contributed to an open source software foundation. The result of which, was mass speculation, fear, uncertainty, and doubt.   Rest assured, Flash is not dead, nor is Flex.

Andrew and Deepa from the Flex team have posted some questions and answers raised by these conversations. I highly recommend reading these in their entirety, as they will answer a lot of the questions about the future of Flex. Key takeaways:

Is Adobe still committed to Flash Builder?

Yes. Flash Builder will continue to be developed and Adobe will work to ensure Flex developers can use Flash Builder as their development tool with future releases of Flex SDK.

Will Adobe continue to support customers using Flex?

Yes. Adobe will continue to honor existing Flex support contracts.

What specifically is Adobe proposing?

We are preparing two proposals for incubating Flex SDK and BlazeDS at the Apache Software Foundation.

In addition to contributing the core Flex SDK (including automation and advanced data visualization components), Adobe also plans to donate the following:

  • Complete, but yet-to-be-released, Spark components, including ViewStack, Accordion, DateField, DateChooser and an enhanced DataGrid.
  • BlazeDS, the server-based Java remoting and web messaging technology that enables developers to easily connect to back-end distributed data and push data in real-time to Flex applications.
  • Falcon, the next-generation MXML and ActionScript compiler that is currently under development (this will be contributed when complete in 2012)
  • Falcon JS, an experimental cross-compiler from MXML and ActionScript to HTML and JavaScript.
  • Flex testing tools, as used previously by Adobe, so as to ensure successful continued development of Flex with high quality

Isn’t Adobe just abandoning Flex SDK and putting it out to Apache to die? 

Absolutely not – we are incredibly proud of what we’ve achieved with Flex and know that it will continue to provide significant value for many years to come. We expect active and on-going contributions from the Apache community. To be clear, Adobe plans on steadily contributing to the projects and we are working with the Flex community to make them contributors as well.

Flex has been open source since the release of Flex 3 SDK. What’s so different about what you are announcing now?

Since Flex 3, customers have primarily used the Flex source code to debug underlying issues in the Flex framework, rather than to actively develop new features or fix bugs and contribute them back to the SDK.

With Friday’s announcement, Adobe will no longer be the owner of the ongoing roadmap. Instead, the project will be in Apache and governed according to its well-established community rules. In this model, Apache community members will provide project leadership. We expect project management to include both Adobe engineers as well as key community leaders. Together, they will jointly operate in a meritocracy to define new features and enhancements for future versions of the Flex SDK. The Apache model has proven to foster a vibrant community, drive development forward, and allow for continuous commits from active developers.

What guarantees can Adobe make in relation to Flex applications continuing to run on Flash Player and Adobe AIR?

Adobe will continue to support applications built with Flex, as well as all future versions of the SDK running in PC browsers with Adobe Flash Player and as mobile apps with Adobe AIR indefinitely on Apple iOS, Google Android and RIM BlackBerry Tablet OS.

-http://blogs.adobe.com/flex/2011/11/your-questions-about-flex.html

Adobe’s Mike Chambers has also posted information explaining a bit more detail, and providing insight into the future of Flash and AIR.   Key takeaways:

Adobe AIR

We are continuing to develop Adobe AIR for both the desktop and mobile devices. Indeed, we have seen wide adoption of Adobe AIR for creating mobile applications and there have been a number of blockbuster mobile applications created using Adobe AIR.

Flash Player for Desktop Browsers

We feel that Flash continues to play a vital role of enabling features and functionality on the web that are not otherwise possible. As such, we have a long term commitment to the Flash Player on desktops, and are actively working on the next Flash Player version.

-http://www.mikechambers.com/blog/2011/11/11/clarifications-on-flash-player-for-mobile-browsers-the-flash-platform-and-the-future-of-flash/


AMF vs. JSON in AIR Mobile Applications

Posted: November 7th, 2011 | Author: | Filed under: ActionScript, AIR, Android, ColdFusion, Development, Flex, iOS | Tags: , , , , , | 12 Comments »

UPDATE 11/23/2011: Full source code now available at:
https://github.com/triceam/Flex-Mobile-Serialization-Tester


Recently, I’ve been asked more than once which is better: AMF or JSON for AIR mobile applications. This post is to highlight some performance comparisons, and a sample testing application that I put together. First, it is important to know what both AMF and JSON are.

AMF

Action Message Format (AMF) is a compact binary format that is used to serialize
ActionScript object graphs. Once serialized an AMF encoded object graph may be used
to persist and retrieve the public state of an application across sessions or allow two
endpoints to communicate through the exchange of strongly typed data.

-from the AMF3 Specficiation

JSON

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition – December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others.

-from www.json.org/

Both AMF and JSON are compact serialization formats and provide efficient data transport.  The main differences between the two formats are as follows:

  • AMF is a binary format that is not easily readable by humans, JSON is a text-based format that is easily readable.
  • AMF allows for serialization of strongly typed objects in transactions between the client and server, JSON only supports generic or loosely-typed objects.

Former Adobe Evangelist James Ward put together a suite of benchmarks comparing JSON, SOAP, and AMF that show comparable performance between AMF and JSON.   Recently, AIR 3.0 and Flash Player 11 brought native JSON support, which greatly improves JSON parsing in Flash & AIR runtimes.   This is a huge boost, especially for mobile applications that consume JSON data.

I put together a very basic test case where a mobile application makes requests of simple data objects from a ColdFusion CFC.  In each test iteration, a request is made for 1, 10, 100, 1000, and 10000 value objects, in both AMF and JSON formats. The total round trip time from request to deserialization is measured and compared for each case, for a total of 5 iterations through each cycle.   My findings are that AMF and JSON have comparable performance in smaller record sets.  However, AMF seems to have better performance as data sets grow.  In my test cases, the 1000+ record results were consistently faster using AMF.  However, in smaller data sets, JSON was often faster (however not consistently, or by much of a margin). I tested these times on both an iPhone 4 and Motorolla Atrix, both running on the carrier networks (not over wifi).

Below is a video of the serialization testing application at work.

Here are a few screenshots of the application.

The Tests

For these tests I created two basic CFCs (ColdFusion Components). One is a simple data value object. The other CFC is a gateway to expose a remote service that returns the value objects to the client. I chose a ColdFusion CFC for this case b/c it can easily be serialized as AMF or JSON just by changing the endpoint used to consume the service.

Here is the basic value object CFC:

component {

	property name="itemId";
	property name="value1";
	property name="value2";
	property name="value3";

	this.itemId = 0;
	this.value1 = CreateUUID();
	this.value2 = CreateUUID();
	this.value3 = CreateUUID()
}

Here is the service CFC used to return data to the client:

component {

	remote array function getRecords(numeric records=1) {
    	var result = [];

        for (var x = 0; x < records; x=x+1) {
        	var item = new SampleVO();
            item.itemId = x;
            ArrayAppend( result, item );
        }

        return result;
    }
}

Obviously, this is a fictional data object with randomly generated values. However, it still represents a reasonable service payload for data serialization. By accessing the data via the ColdFusion Flex/Remoting gateway, you access the remote services via AMF3.

remoteObject = new RemoteObject("ColdFusion");
remoteObject.source = "com.tricedesigns.mobileTest.Services";
remoteObject.endpoint = "http://tricedesigns.com/flex2gateway/";

var token : AsyncToken = remoteObject.getRecords( RECORD_COUNT[ recordCountIndex ] );
token.addResponder( new mx.rpc.Responder( onAMFResult, onFault ) );

By accessing the data via an http endpoint, with returnformat=josn, you will invoke the same CFC remote method exposed as JSON.

httpService = new HTTPService();

httpService.url = "http://tricedesigns.com/com/tricedesigns/mobileTest/Services.cfc?method=getrecords&records=" + RECORD_COUNT[ recordCountIndex ] + "&returnformat=json";
var token : AsyncToken = httpService.send();
token.addResponder( new mx.rpc.Responder( onJSONResult, onFault ) );

The JSON-formatted data will look something like this:

[{"ITEMID":0,"VALUE3":"FA817ED6-EB7C-0677-097452161BCB6689","VALUE2":"FA817ED5-0FC4-BD8B-6515B283E5426AAC","VALUE1":"FA817ED4-0B3A-71B4-D45559FBB0AE5BEE"},
{"ITEMID":1.0,"VALUE3":"FA817ED9-FBBE-B9A2-9C01390B65B65DDB","VALUE2":"FA817ED8-A5EF-EE8E-72692303F9C5CFCB","VALUE1":"FA817ED7-D569-2008-A5BFB9F6E1154FE6"},
{"ITEMID":2.0,"VALUE3":"FA817EDC-FC4E-3473-6FC7910831CB293A","VALUE2":"FA817EDB-DF92-71D5-B6B5C67EC93816DD","VALUE1":"FA817EDA-90A3-1566-96FC2524628DCB56"},
{"ITEMID":3.0,"VALUE3":"FA817EDF-923A-DC19-07128DF719212B97","VALUE2":"FA817EDE-E59F-40F0-FE3A9267DE952E8E","VALUE1":"FA817EDD-B0F0-5B20-675E0B0A61D4DA46"},
{"ITEMID":4.0,"VALUE3":"FA817EE2-CDCA-5C3D-88D3B72EEF11AA60","VALUE2":"FA817EE1-99D3-741D-58F5BA5DC00C035F","VALUE1":"FA817EE0-F1AB-0AEF-2FC57BA2104FB365"},
{"ITEMID":5.0,"VALUE3":"FA817EE5-0750-E4A5-18914030A5EC4BF2","VALUE2":"FA817EE4-07A4-D025-16BF02A7452F3EC2","VALUE1":"FA817EE3-E72B-B8CA-F22607314115CACF"},
{"ITEMID":6.0,"VALUE3":"FA817EE8-AC14-79D7-6F2BF568CE172823","VALUE2":"FA817EE7-95B8-9BA8-9265B6BAFF927D48","VALUE1":"FA817EE6-FCD4-2998-965667E97F515AB5"},
{"ITEMID":7.0,"VALUE3":"FA817EEB-E5F2-F2AB-FE68B85311E126B0","VALUE2":"FA817EEA-C93B-65FF-C7867A6A097BA1FC","VALUE1":"FA817EE9-B009-EC7E-BA063963F0E905E9"},
{"ITEMID":8.0,"VALUE3":"FA817EEE-C060-FD2E-B611E38AC454A789","VALUE2":"FA817EED-BED5-79F3-E6F72A823B92B5D9","VALUE1":"FA817EEC-F930-7069-52DB96A08D828F6B"},
{"ITEMID":9.0,"VALUE3":"FA817EF1-AABB-8AE0-0D1141E449A99A4F","VALUE2":"FA817EF0-0E1C-C0AD-2446C0706A87C9DF","VALUE1":"FA817EEF-0899-5737-A53E353397F401CF"}]

In the mobile client application, I have a SerializationTestController class that handles all of the test logic and communications back and forth with the server. The time for each test is measured from immediately before the the request is made to the server, until after the data has been deserialized to an ArrayCollection. You can view the SerializationTestController class below:

package control
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.utils.getTimer;

	import model.TestSummaryVO;
	import model.TestVO;

	import mx.collections.ArrayCollection;
	import mx.rpc.AsyncToken;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	import mx.rpc.remoting.RemoteObject;

	import views.SummaryView;

	[Event(name="testStatusChange", type="control.TestUpdateEvent")]
	[Event(name="testUpdate", type="control.TestUpdateEvent")]
	public class SerializationTestController extends EventDispatcher
	{
		private var remoteObject : RemoteObject;
		private var httpService : HTTPService;

		private var _testing : Boolean = false;

		private var testIndex : int = 0;
		private var iterationIndex : int = 0;
		private var recordCountIndex : int = 0;
		private var testInstanceIndex : int = 0;

		private var _results : ArrayCollection;
		private var currentTest : TestVO;

		public static const ITERATIONS : int = 5;
		public static const RECORD_COUNT : Array = [1,10,100,1000,10000];
		public static const TESTS : Array = [ TestVO.TYPE_AMF, TestVO.TYPE_JSON ];

		public function SerializationTestController(target:IEventDispatcher=null)
		{
			super(target);

			remoteObject = new RemoteObject("ColdFusion");
			remoteObject.source = "com.tricedesigns.mobileTest.Services";
			remoteObject.endpoint = "http://tricedesigns.com/flex2gateway/";

			httpService = new HTTPService();

			_results = new ArrayCollection();
		}

		[Bindable(event="testStatusChange")]
		public function get testing ():Boolean
		{
			return _testing;
		}

		public function get results():ArrayCollection
		{
			return _results;
		}

		public function get chartResults() : ArrayCollection
		{
			var result : ArrayCollection = new ArrayCollection();

			for ( var index : int = 0; index < ITERATIONS; index++ ) 			{ 				var summaryVO : TestSummaryVO = new TestSummaryVO(); 				summaryVO.iteration = index+1; 				result.addItem( summaryVO ); 			} 			 			for each ( var vo : TestVO in results ) 			{ 				summaryVO = result.getItemAt( vo.iteration ) as TestSummaryVO; 					 				if ( vo.type == TestVO.TYPE_AMF ) 					summaryVO[ "amfDuration" + SerializationTestController.RECORD_COUNT[ vo.recordIndex ] ] = vo.endTime - vo.startTime; 				else 					summaryVO[ "jsonDuration" + SerializationTestController.RECORD_COUNT[ vo.recordIndex ] ] = vo.endTime - vo.startTime; 				 			} 			 			return result; 		} 		 		 		 		public function startTest() : void 		{ 			if ( _testing )  return; 			 			_testing = true; 			testIndex = 0; 			iterationIndex = 0; 			recordCountIndex = 0; 			testInstanceIndex = 0; 			updateTest(); 			dispatchEvent( new TestUpdateEvent( TestUpdateEvent.TEST_STATUS ) ); 			dispatchEvent( new TestProgressEvent( "STARTING TEST..." ) ); 		} 		 		private function completeTest() : void 		{ 			_testing = false; 			dispatchEvent( new TestUpdateEvent( TestUpdateEvent.TEST_STATUS ) ); 			dispatchEvent( new TestProgressEvent( "TEST COMPLETE" ) ); 		} 		 		private function createTestVO() : void 		{ 			currentTest = new TestVO(); 			currentTest.startTime = getTimer(); 			currentTest.index = testInstanceIndex; 			currentTest.iteration = iterationIndex; 			currentTest.recordIndex = recordCountIndex; 			currentTest.type = TESTS[ testIndex ]; 		} 		 		private function finalizeTestVO(error : Boolean = false) : void 		{ 			if ( error ) 				currentTest.endTime = -1 			else 				currentTest.endTime = getTimer(); 			 			_results.addItem( currentTest ); 			dispatchEvent( new TestUpdateEvent( TestUpdateEvent.TEST_UPDATE,  currentTest ) ); 			dispatchEvent( new TestProgressEvent( "task completed in " + (currentTest.endTime - currentTest.startTime) + " milliseconds" ) ); 			currentTest = null; 		} 		 		private function updateTest() : void 		{ 			if ( iterationIndex >= ITERATIONS )
				return completeTest();

			createTestVO();

			if ( TESTS[ testIndex ] == TestVO.TYPE_AMF )
			{
				doAMFTest();
				recordCountIndex ++;

				if ( recordCountIndex >= RECORD_COUNT.length )
				{
					recordCountIndex = 0;
					testIndex++;
				}
			}

			else if ( TESTS[ testIndex ] == TestVO.TYPE_JSON )
			{
				doJSONTest();
				recordCountIndex ++;

				if ( recordCountIndex >= RECORD_COUNT.length )
				{
					recordCountIndex = 0;
					testIndex = 0;
					iterationIndex ++;
				}
			}

			testInstanceIndex++;
		}

		private function doAMFTest() : void
		{
			dispatchEvent( new TestProgressEvent( "AMF Requesting " + RECORD_COUNT[ recordCountIndex ] ) );
			var token : AsyncToken = remoteObject.getRecords( RECORD_COUNT[ recordCountIndex ] );
			token.addResponder( new mx.rpc.Responder( onAMFResult, onFault ) );
		}

		protected function onAMFResult( event : ResultEvent ) : void
		{
			var result : ArrayCollection = event.result as ArrayCollection;
			finalizeTestVO();
			updateTest();
		}

		private function doJSONTest() : void
		{
			dispatchEvent( new TestProgressEvent( "JSON Requesting " + RECORD_COUNT[ recordCountIndex ] ) );
			httpService.url = "http://tricedesigns.com/com/tricedesigns/mobileTest/Services.cfc?method=getrecords&records=" + RECORD_COUNT[ recordCountIndex ] + "&returnformat=json";
			var token : AsyncToken = httpService.send();
			token.addResponder( new mx.rpc.Responder( onJSONResult, onFault ) );
		}

		protected function onJSONResult( event : ResultEvent ) : void
		{
			var resultString : String = event.result as String;
			var result : ArrayCollection = new ArrayCollection( JSON.parse( resultString ) as Array );

			finalizeTestVO();
			updateTest();

		}

		protected function onFault( event : FaultEvent ) : void
		{
			trace( event.fault.toString() );
			finalizeTestVO(true);
			updateTest();
		}

	}
}

Also, here is the TestVO value object that shows the information captured for each test:

package model
{
	public class TestVO
	{
		public static const TYPE_JSON : String = "json";
		public static const TYPE_AMF : String = "amf";

		public var index : int;
		public var iteration : int = 0;
		public var startTime : int;
		public var endTime : int;
		public var type : String;
		public var recordIndex : int;

		public function TestVO()
		{
		}
	}
}

Summary

Both JSON and AMF are acceptable serialization formats for mobile applications built with AIR.   Both are compact serialization formats that minimize packet size.  Both have native parsing/decoding by the AIR runtime.   AMF will generally provide better performance for larger data sets.  JSON *may* provide marginally better performance for small data sets.  AMF also allows for strongly typed object serialization & deserialization, where JSON does not.

The answer to the question of “should I use AMF or JSON” is subjective… What kind of data are you returning, and how much data is it? Do you already have AMF services built?  Do you already have JSON services built?   Are the services consumed by multiple endpoints, with multiple technologies?  Do you rely upon strongly typed objects in you development and maintenance processes?  Both AMF and JSON are viable solutions for mobile applications.


UPDATE 11/23/2011: Full source code now available at:
https://github.com/triceam/Flex-Mobile-Serialization-Tester


Thanks also to fellow Adobe evangelist Raymond Camden for the CF tips & guidance.


Infinitely Scrolling Lists in Flex Applications

Posted: October 26th, 2011 | Author: | Filed under: ActionScript, Adobe, AIR, Android, Development, Flex, iOS, Mobile | Tags: , , | 6 Comments »

Have you noticed when using twitter, google plus, or certain areas of facebook that when you scroll the page, it automatically loads more data?  You don’t have to continually hit “next” to go through page after page of data. Instead, the content just “appears” as you need it. In this post we will explore a technique for making Flex list components behave in this exact way. As you scroll through the list, it continually requests more data from the server. Take a look at the video preview below, and afterwards we’ll explore the code.

The basic workflow is that you need to detect when you’ve scrolled to the bottom of the list, then load additional data to be displayed further in that list. Since you know how many records are currently in the list, you always know which “page” you are viewing. When you scroll down again, just request the next set of results that are subsequent to the last results that you requested. Each time you request data, append the list items to the data provider of the list.

First things first, you need to detect when you’ve scrolled to the bottom of the list. Here’s a great example showing how to detect when you have scrolled to the bottom of the list. You can just add an event listener to the list’s scroller viewport. Once you have a vertical scroll event where the new value is equal to the viewport max height minus the item renderer height, then you have scrolled to the end. At this point, request more data from the server.

One other trick that I am using here is that I am using conditional item renderers based upon the type of object being displayed. I have a dummy “LoadingVO” value object that is appended to the end of the list data provider. The item renderer function for the list will return a LoadingItemRenderer instance if the data passed to it is a LoadingVO.

Here it is up close, in case you missed it:

Here’s my InfiniteScrollList class:

package components
{
	import model.InfiniteListModel;
	import model.LoadingVO;

	import mx.core.ClassFactory;
	import mx.events.PropertyChangeEvent;

	import spark.components.IconItemRenderer;
	import spark.components.List;

	import views.itemRenderer.LoadingItemRenderer;

	public class InfiniteScrollList extends List
	{
		override protected function createChildren():void
		{
			super.createChildren();
			scroller.viewport.addEventListener( PropertyChangeEvent.PROPERTY_CHANGE, propertyChangeHandler );
			itemRendererFunction = itemRendererFunctionImpl;
		}	

		protected function propertyChangeHandler( event : PropertyChangeEvent ) : void
		{
			//trace( event.property, event.oldValue, event.newValue );

			if ( event.property == "verticalScrollPosition" )
			{
				if ( event.newValue == ( event.currentTarget.measuredHeight - event.currentTarget.height ))
				{
					fetchNextPage();
				}
			}
		}

		protected function fetchNextPage() : void
		{
			if ( dataProvider is InfiniteListModel )
				InfiniteListModel( dataProvider ).getNextPage();
		}

		private function itemRendererFunctionImpl(item:Object):ClassFactory
		{
			var cla:Class = IconItemRenderer;
			if ( item is LoadingVO )
				cla = LoadingItemRenderer;
			return new ClassFactory(cla);
		}
	}
}

You may have noticed in the fetchNextPage() function that the dataProvider is referenced as an InfiniteListModel class… let’s examine this class next. The InfiniteListModel class is simply an ArrayCollection which gets populated by the getNextPage() function. Inside of the getNextPage() function, it calls a remote service which returns data to the client, based on the current “page”. In the result handler, you can see that I disable binding events using disableAutoUpdate(), remove the dummy LoadingVO, append the service results to the collection, add a new LoadingVO, and then re-enable binding events using enableAutoUpdate(). Also, notice that I have a boolean _loading value that is true while requesting data from the server. This boolean flag is used to prevent multiple service calls for the same data.

Let’s take a look at the InfiniteListModel class:

package model
{
	import flash.events.Event;
	import flash.utils.setTimeout;

	import mx.collections.ArrayCollection;
	import mx.rpc.AsyncToken;
	import mx.rpc.Responder;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.remoting.RemoteObject;

	public class InfiniteListModel extends ArrayCollection
	{
		private var _remoteObject : RemoteObject;

		protected var _loading : Boolean = false;

		public function get remoteObject():RemoteObject
		{
			return _remoteObject;
		}

		public function set remoteObject(value:RemoteObject):void
		{
			_remoteObject = value;
			if ( _remoteObject )
				getNextPage();
		}

		public function InfiniteListModel(source:Array=null)
		{
			super(source);
			addItem( new LoadingVO() );
		}

		public function getNextPage() : void
		{
			if ( !_loading)
			{
				_loading = true;

				trace( "fetching data starting at " + (this.length-1).toString() );
				var token : AsyncToken = remoteObject.getData( this.length-1 );
				var responder : Responder = new Responder( resultHandler, faultHandler );
				token.addResponder( responder );
			}
		}

		protected function resultHandler(event:ResultEvent):void
		{
			this.disableAutoUpdate();

			if ( this.getItemAt( this.length-1 ) is LoadingVO )
				this.removeItemAt( this.length-1 );

			for each ( var item : * in event.result )
			{
				addItem( item );
			}
			addItem( new LoadingVO() );
			this.enableAutoUpdate();

			_loading = false;
		}

		protected function faultHandler(event:FaultEvent):void
		{
			trace( event.fault.toString() );
		}
	}
}

Now, let’s take a look at the root view that puts everything together. There is an InfiniteScrollList whose dataProvider is an InfiniteListModel instance. The InfiniteListModel also references a RemoteObject instance, which loads data from a remote server.

<?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="Infinite Scroll"
		xmlns:model="model.*"
		xmlns:components="components.*">

	<fx:Declarations>
		<model:InfiniteListModel id="infiniteListModel"
								 remoteObject="{ remoteObject }" />

		<s:RemoteObject id="remoteObject"
						destination="ColdFusion"
						source="com.tricedesigns.infiniteScroll.Services"
						endpoint="http://tricedesigns.com/flex2gateway/" />
	</fx:Declarations>

	<components:InfiniteScrollList
			id="list"
			width="100%" height="100%"
			dataProvider="{ infiniteListModel }" />

</s:View>

Let’s not forget the remote service. In this case, I’m calling into a very basic remote CFC that returns an Array of string values. You can see the code below:

<cfcomponent>

	<cffunction name="getData" access="remote" returntype="array">
		<cfargument name="startIndex" type="numeric" required="yes">

        <cfset items = ArrayNew(1)>
        <cfloop from="1" to="25" index="i">
         	<cfset item = "item " & (i+startIndex)>
            <cfset ArrayAppend( items, item )>
         </cfloop>

		<cfreturn items>
	</cffunction>

</cfcomponent>

You can download the full source code for this application directly from here:
http://tricedesigns.com/portfolio/infiniteScroll/infiniteScroll.zip


Why Cross Platform Mobile Development?

Posted: October 20th, 2011 | Author: | Filed under: Adobe, AIR, Android, Development, Flex, HTML5, iOS, Mobile, PhoneGap | Tags: , , , , , , | 3 Comments »

Perhaps you have heard of the topic “cross platform development”, but aren’t really sure what it is, or you aren’t sure why you would want to use cross-platform technologies. If this is the case, then this post is especially for you. I’ll try to shed some light onto what it is, and why you would want to use cross-platform development strategies.

What is cross-platform development?

Cross platform development is a concept in computer software development where you write application code once, and it runs on multiple platforms. This is very much inline with the “write once, run everywhere” concept pioneered in the 90s, and brought to a mainstream reality with Flash in the browser, and AIR on the desktop. The standard evolution of technology has been to make everything faster, smaller, and more portable, and it is only natural that that this concept has now come into the mobile development world. In mobile scenarios, it is applied by writing an application using a codebase & technology that allows the application to be deployed and distributed across multiple disparate platforms/operating systems/devices.

Using Adobe AIR, this includes Apple’s iOS devices (iPhone and iPad), Android (a plethora of devices), BlackBerry Playbook & upcoming BBX platform, and soon Windows Metro (the tablet offering of Windows 8).   Using PhoneGap, this includes Apple iOS, Android, BlackBerry 4.6 and higher, HP WebOS, Symbian, Samsung Bada, and Windows Phone 7 – Mango platforms.

In case you’re wondering why I offered 2 cross platform technologies, that is because Adobe will soon have 2 cross-platform product offerings.  Adobe has entered an agreement to purchase Nitobi, the creators of PhoneGap.

Adobe AIR

Adobe AIR is a cross-platform technology with roots in the Flash Player and the AIR desktop runtime.  AIR allows you to build cross-platform mobile applications using ActionScript and the open source Flex framework.   AIR apps can be built from the Flash Professional timeline-based design/animation tool, Flash Builder (an Eclipse-based development environment), or other open source solutions using the freely available AIR SDK.   Applications developed with Adobe AIR can target desktop platforms (Mac, & Windows), smart phone and tablet platforms (iOS, Android, BlackBerry, soon Windows), and even smart televisions.

PhoneGap (Apache Callback)

PhoneGap is an open source cross platform technology with roots in the HTML world. Essentially, a PhoneGap application consists of a web view that consumes 100% of the available width & 100% of the available height, taking advantage of web browsers on each platform.   PhoneGap offers a JavaScript to native bridge that enables you to build natively-installed applications using HTML and JavaScript, using the native bridge to interact with the device hardware/APIs.   Note: PhoneGap is also being submitted to the Apache Foundation as the Apache Callback project.

More Devices, Less Code

The driving factor behind cross-platform technologies is that you will be able to use those technologies to target more devices & platforms, with writing a minimal amount of source code.   There are many advantages with this approach.  Here are a few of the major reasons…

Lower Barrier of Entry

Generally speaking, development with HTML & JavaScript or Flex & ActionScript is easier than developing with Objective-C or Java.   Due to the ease of use of the development tooling and familiarity of the languages, cross platform technologies lower the technical barriers which may have prevented adoption of native development.  This allows your development team to build applications that they may not previously have been able to, and also enables your team to focus on what matters – the application; not the skills required to develop on multiple disparate platforms.

Reduce the Number of Required Skills for the Development Team

Native development on multiple platforms requires your development team to learn Objective C for iOS applications, Java for Android applications, Silverlight for Windows Phone applications, etc…   Finding all of these skills in a single developer is nearly impossible.   Using cross-platform development technologies, your team only needs to be proficient with one language/skillset.  Knowledge of the native development paradigms and languages are always a plus, but are no longer a requirement.   Many developers transitioning from web development already know either Flex/ActionScript and/or HTML/JavaScript, and making the transition from web to mobile development will not be a major undertaking.

Reduced Development & Long Term Maintenance Costs

Cross-platform mobile applications can originate from a single codebase, which requires a single development skillset.  You don’t need to have staff for each individual platform.  Instead, resources working on the shared codebase can cover all target platforms.   Having a single codebase also reduces long term maintenance costs.  You no longer need to have bug tracking for X number of codebases, and do not need to maintain a larger staff to support each platform.  Did I also mention that you have one codebase to maintain?

Having a single codebase doesn’t reduce the need for QA/testing on each target platform – nothing can get rid of this.  It is absolutely imperative that you test your codebase on physical devices for all platforms that you intend to support.   Emulators and Simulators can go a long way during development, but they will undoubtedly not cover all scenarios possible on a physical device, and they will not have the same runtime performance as a physical device.

Play the Strengths of a Technology

Some technologies make tasks easier than others.   For example, programmatic drawing and data visualization are very easy using Flex & ActionScript.   Developing equivalent experiences in native code can be significantly more complex and time consuming.   Use the the features of the language to their fullest potential, to your advantage- that’s why they exist.


Scrolling Large Blocks of Text with Flex for Mobile

Posted: October 11th, 2011 | Author: | Filed under: AIR, Android, Flex, iOS, Mobile, Uncategorized | Tags: , , , , | 1 Comment »

I was recently asked by a friend and former colleague about the best way to get text within a s:Label to behave and scroll properly, especially in the Flex mobile SDK. In particular, having a large block of text wrap correctly and scroll only in the vertical direction. By default if you don’t set a size on the label, the behavior of the Flex framework is that the views containing the label will resize, and the text will be displayed as entered (without word wrap or truncation). This may cause some layout issues and confusion as to “what the heck is going on with my text”.

I’ve found that the best way to achieve the desired behavior is to set a maxWidth on the label to force proper word wrapping, and then wrap the label in a s:Scroller to have it scroll properly. I chose to set a maxWidth to allow the label to determine it’s own size, and only to wrap if it needs to. An easy shortcut for proper wrapping is to bind the maxWidth of the label to the width of the scroller component. Also, DO NOT set a static height or a max height. This will cause the text within the label to be truncated, and it will not scroll at all if the static height is less than the height of the scroller. I’ve also noticed that setting cacheAsBitmap=true on the label also helps scroll performance in some circumstances, but this is not required.

Check out a video showing the scroll behavior of a large text block using this approach:

Below is the code that makes it work, which follows the method described above:

<s:Scroller height="100%" width="100%" id="scroller1">
	<s:Group>
		<s:Label id="labelInstance"
				 cacheAsBitmap="true"
				 maxWidth="{ scroller1.width }"
				 color="#FF0000" fontSize="32">
			<s:text>Bacon ipsum dolor sit amet sint cow irure et magna, meatball aliquip qui. Tempor turkey capicola, eiusmod sed nisi dolore. Pig nisi rump boudin in culpa chuck. In ex sausage filet mignon shankle ut. Flank ball tip cillum aute. Nulla frankfurter culpa, elit et esse aute pork salami. Laborum mollit short ribs, in meatloaf eu irure dolor consectetur elit strip steak.

				{note: text has been truncated to emphasize actual code, not the random text}
			</s:text>
		</s:Label>
	</s:Group>
</s:Scroller>

This post is also “powered by bacon”… yes, bacon.


MAX 2011 Presentations

Posted: October 10th, 2011 | Author: | Filed under: Adobe, AIR, Development, Flex, HTML5, Mobile | Tags: , , , , , , | No Comments »

The recordings of my presentations don’t seem to be available yet on Adobe TV, but here is the content, as promised. I spoke at MAX this year on “Multi Device Best Practices using Flex & AIR for Mobile”, and “Create beautiful, immersive content and applications with HTML5 and CSS3″, and the content from these presentations is below.

Multi Device Best Practices using Flex & AIR for Mobile

In the multi-device best practices session I covered the basics for building a multi-device/multi-form-factor application that conforms to device constraints (phone and tablet), using a single codebase that is able to detect device dimensions and orientation.  This was followed by online/offline detection for occasionally-connected applications, and then followed by device-specific layout using CSS media queries and MultiDPIBitmapSource images.  The presentation slides are below.

Direct links to download the content:

In this presentation, I also showed and discussed my airplane tracking application demo, discussed here (with full source).

Create beautiful, immersive content and applications with HTML5 and CSS3

In this session, I gave a “crash course” in developing rich content experiences with HTML5 and CSS3.   I started with a general overview presentation, followed by diving directly into code.   I covered <video>, <audio>, dynamic graphics with <canvas>, <svg>, HTML5 Form elements, CSS3 Web Fonts, Visual Styles (shadows, corners), CSS3 Color spaces (RGBA, HSLA), graidents, transforms, animations, and media queries.  In the presentation, I also discussed the necessity of client-side solution accelerator frameowrks (jQuery or other JS framework), in addition to graceful degradation and HTML5 feature detection using Modernizr.  The presentation slides are below:

Direct links to download the content:


Flash/Flex/AIR Platform Roadmap 2011

Posted: October 7th, 2011 | Author: | Filed under: Adobe, AIR, Development, Flex | Tags: , , , , , , | 2 Comments »

Although there were no official announcements around Flex, Flash & AIR (other than the release of FP11 & AIR3), don’t think that the platform is going away or becoming stale… In fact, it is quite the opposite. The Flash Platform will continue to thrive and innovate, providing outstanding solutions that set the pace for other technologies to follow. In case you missed the session, here is the “Flash Platform Roadmap”, provided by Scott Castle, Adam Lehman, and Raghu Thricovil, Product Managers for Flash Platform tooling:

If that wasn’t enough, did you see the new “Monocle” tool, shown by Deepa Subramaniam? Monocle is the new realtime profiling tool for Flash-based content which will provide additional insight into what’s happening at runtime, and how you can optimize your applications.

Did you also see the latest demos showing the Epic Games & the Unreal engine running INSIDE of the Flash Player?

Yes, this is really the Flash Player. You can read more here.


Object Orientation

Posted: September 29th, 2011 | Author: | Filed under: ActionScript, AIR, Development, Flex | Tags: , | No Comments »

Here’s another post that I originally wrote way back in 2006, when object oriented development was a newer concept to client-side web applications. Again, this post is still very relevant with Flex, AIR & ActionScript for mobile/web/desktop, so I decided to resurrect it from the old blog archive as well. Enjoy…

Understanding of OOP (Object Oriented Programming) is fundamental in being successful with the Flex framework and being able to get the most out of it. Developers who do not possess a computer science-related background may not be aware of the fundamental concepts that comprise OOP and how to apply them correctly, so here is a quick piece to help you out.

First, object oriented programming is a programming paradigm where your code is organized into logical objects, and each object has properties and methods. Each object contains similar and/or related functionality, and is organized into classes that logically represent and logically organize it’s functionality.

For Example:
Let’s say that we have a class “Automobile”. This class would contain the information and functions necessary for our application to use the Automobile class. We could have a numeric property for the number of wheels, the speed, and the direction (degrees on a compass). This class would also contain methods that control the actions of the Automobile object: accelerate, decelerate(break), turn, start engine, stop engine, etc… Our class would look something like this…

public class Automobile
{
	public var speed : Number;
	public var direction : Number;
	public var numWheels : Number;

	public function Automobile()
	{ /* constructor */ }

	public function accelerate() : void
	{ /* speed up the automobile */ }

	public function decelerate() : void
	{ /* slow down the automobile */ }

	public function turn( direction : Number ) : void
	{ /* turn the automobile */ }

	public function startEngine() : void
	{ /* start the automobile engine */ }

	public function stopEngine() : void
	{ /* stop the automobile engine */ }
}

Ok, now that we have a brief explanation of what object oriented programming is, we can get into some more aspects of OOP: inheritance and interfaces.

Inheritance is a way to form new objects based on existing objects. When a class inherits from a base class, the new class extends the functionality of the base class, and can utilize public and protected properties and methods from that base class. Inheritance can be used to create different objects that utilize functions within the base class, so that the child classes all utilize the same code base. Inheritance can be used to extend the functionality of existing objects, and inheritance can also be used to override and/ or change functionality from the base class.

In Actionscript 3, you can access the parent class of your class by using the “super” keyword. For instance, calling the constructor of the parent class would use “super()”, where accessing a method of the parent class would use something like: “super.myMethodName()”. If a property of the parent class is created with public or protected access, you can access that property in the child class directly by the property name (you would use this.propertyName, not super.propertyName).

Now, Lets take our Automobile example and apply object-oriented inheritance. We already have a base Automobile class that covers the basic functionality. We can create child classes that extend the functionality of the Automobile.

public class SportsCar extends Automobile
{
	public function SportsCar()
	{
		super();
	}

	override public function accelerate():void
	{
		/* we can override the accelerate function
		     so that it accelerates faster than the base
		     Automobile */
	}
}

and…

public class Truck extends Automobile
{
	public function Truck()
	{
		super();
	}

	public function tow() : void
	{
		/* we can add a tow function that
		   allows the Automobile class to tow
		   items. */
	}
}

These classes extend the base functionality of the Automobile class, and therefore are instances of the Automobile class. If we have a function outside of the Automobile class, which takes an automobile as the parameter, both a SportsCar and Truck will work since they are both Automobiles. We could have a function such as the following: If we pass in a Truck Instance, and a SportsCar instance, both will work, and each will use the functionality of their specific class instead of the base Automobile class.

public function race( auto1 : Automobile, auto2 : Automobile ) : void
{
	auto1.accelerate();
	auto2.accelerate();
}

I’ll get into some more fine-grain details about inheritance later in this post… now, lets move on to interfaces…

Interfaces are slightly different than inheritance. An interface is a set of “rules” which an object must adhere to. The “rules” are actually method signatures that your class must implement. When we define an interface, we define method signatures that are required for classes that implement that interface. There is no actual code in an interface; it simply defines methods that must exist within your class. Your class that implements the interface must implement the code for the actual function. If you have multiple classes that implement an interface, those classes must have the same functions (only the ones required by the interface), but that is where the similarities of the two classes may stop. They could have completely different logic and properties within them… this is where inheritance and interfaces differ. Two objects that inherit from the same base class have a lot in common (properties and methods): two objects that implement the same interface only have those interface method signatures in common.

Let’s now make an Automobile Interface that defines the functions required to create an IAutomobile object (note the “I” stands for “interface”):

public interface IAutomobile
{
	function accelerate() : void;
	function decelerate() : void;
	function turn( direction : Number ) : void;
}

We can use the IAutomobile interface to create objects (classes) that behave as Automobile objects. These classes do not necessarily inherit from each other and do not necessarily share any common properties.

public class Car implements IAutomobile
{
	private var direction:Number;
	private var speed:Number;

	public function turn(direction:Number):void
	{
		this.direction = direction;
	}

	public function decelerate():void
	{
		this.speed++;
	}

	public function accelerate():void
	{
		this.speed--;
	}
}
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas implements="IAutomobile"
	xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:Script>
		<![CDATA[

			private var direction:Number;
			private var speed:Number;

			public function turn(direction:Number):void
			{
				this.direction = direction;
			}

			public function decellerate():void
			{
				this.speed++;
			}

			public function accellerate():void
			{
				this.speed--;
			}
		]]>
	</mx:Script>
</mx:Canvas>

The previous two components both implement the IAutomobile interface, but have nothing else in common. One is simply a class that implements the interface, the other is a mxml component that implements the interface. The mxml component example extends the mx:Canvas component (the same thing could be done by creating an AS class that extends mx.containers.Canvas). Now, lets look at a function similar to the “race” function from earlier…

public function race( auto1 : IAutomobile, auto2 : IAutomobile ) : void
{
	auto1.accelerate();
	auto2.accelerate();
}

This example will work with either object that I have created because both objects implement the IAutomobile interface. They do not rely upon functions in the class hierarchy, just those that were implemented for this interface. You can also use multiple interfaces on classes that you create. Implementing multiple interfaces basically means that you are adding more required method signatures to your class, and you will have to implement these methods to satisfy each interface.

On the other hand, you cannot inherit from multiple classes. Some programming languages allow for multiple inheritance… ActionScript 3 does not support multiple inheritance (so i’ll stop there).

OK… enough of this rambling… What does this have to do with Flex?
Inheritance and interfaces are used extensively in AS3 to create the flex framework. All flex framework components that are rendered to the screen extend from the UIComponent class. AbstractService, DataSerice or EventDispatcher object implements the IEventDispatcher Interface. You may be using these concepts every day, but weren’t aware of them. Inheritance seems easier to take advanatage of at first… Lets say that you want to create several objects, all of which will have identical functions and variables. It is easy to see that you can create a base class that encapsulates all of the common functionality. You can then create a sub-classes that implement the differing functionality for each class.

When putting these concepts into real-world Flex applications you’ll need to get familiar with the following keywords:

extends
This is used when defining a child class from a parent class.

public class MyImage extends Image

implements
This is used when implementing an interface.

public class MyClass implements MyInterface

final
Classes and methods implented with “final” cannot be overridden.

final function myFunction() : void

static
The static keyword is used when creating variables or functions in a class that are specific to the class, not an instance. Static properties and methods do not require variable instantiation to be executed.

public static function myStaticFunction(): void
//to use it call it directly from ClassMyClass.myStaticFunction()

internal
This is used when creating a method or property that can be accessed by any object within the same package (namespace)

internal var foo : String;

override
This is used when creating a function that overrides another function from a parent class.

override public function myFunction() : void

private
This is used when creating methods or properties that are only available to the class where it is defined. A private variable cannot be accessed by outside classes or from descendant classes.

private var myPrivateValue : String;

protected
This is used when creating methods or properties that are only available to the class where it is defined and descendant classes. A protected variable cannot be accessed by outside classes.

protected var myProtectedValue : String;

public
This is used when creating properties and methods that are available to any class.

public var myPublicValue : String;

Flex for Mobile – Device Form Factor Detection

Posted: September 29th, 2011 | Author: | Filed under: ActionScript, Adobe, AIR, Android, Flex, iOS, Mobile | Tags: , , , , | 3 Comments »

Here’s a quick tip for detecting device form factor (tablet vs phone) within your Flex mobile applications. First, get the stage dimensions for the screen size in pixels, then divide that by the applicationDPI (screen pixel density).  This will give you the approximate size in inches of the device’s screen.   I say “approximate” because the pixel densities are rounded to 160, 240, or 320, depending on the device.    In my code, I make the assumption that if the landscape width is greater than or equal to 5 inches, then its a tablet.  I used view states, but you can also layout components manually.

Check out the 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"
		xmlns:views="views.*"
		resize="view1_resizeHandler(event)">

	<fx:Script>
		<![CDATA[

			import mx.core.FlexGlobals;
			import mx.events.ResizeEvent;

			protected function view1_resizeHandler(event:ResizeEvent):void
			{
				var _width : Number = Math.max( stage.stageWidth, stage.stageHeight );
				var _height : Number = Math.min( stage.stageWidth, stage.stageHeight );

				_width = _width / FlexGlobals.topLevelApplication.applicationDPI;
				_height = _height / FlexGlobals.topLevelApplication.applicationDPI;

				//this will resolve to the physical size in inches...
				//if greater than 5 inches, assume its a tablet
				if ( _width >= 5 )
					currentState = "tablet";
				else
					currentState = "phone";
			}

		]]>
	</fx:Script>

	<s:states>
		<s:State name="tablet" />
		<s:State name="phone" />
	</s:states>

	<views:PhoneView includeIn="phone"
					 width="100%" height="100%" />

	<views:TabletView includeIn="tablet"
					  width="100%" height="100%" />

</s:View>

This technique will enable you to build applications that tailor their interface to the types of devices where they are being consumed. If you’d like to read more, fellow Adobe Evangelist Michael Chaize also has a great example showing how to combine device form factor and orientation into Flex view states.