Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / Adobe AIR Developer Center /

Multiscreen development techniques with Flex and Adobe AIR

by Mark Ellis

Mark Ellis

by Dylan DePass

Dylan DePass

Content

  • Parsley overview
  • Package structure
  • Skinning and styling
  • Presentation models and screen design
  • Commands and Events
  • Screen management
  • Where to go from here

Created

11 October 2010

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
ActionScript Adobe AIR desktop Flash Builder Flex mobile multiscreen

Requirements

User level

Intermediate

Required products

  • Flash Builder 4 (Download trial)
  • Adobe AIR
  • Flex (Download trial)

Sample files

  • Empdir-SampleCode.zip (25036 KB)

This article discusses and explains techniques our team has developed through the creation and deployment of an enterprise application across multiple screens. It provides an overview followed by concrete examples and sample code that achieve the most code reuse between screens. The sample code uses the AIR 2.5 runtime for the Android platform which is currently in prerelease.

This application was built prior to the announcement of Flex SDK "Hero" and the sample code is compiled and built with Flex 4.1. However, the techniques explained here can be applied to Flex SDK "Hero". Upon its release, we recommend building your multiscreen applications with it.

Note: Be sure to watch Senior Evangelist Ron Nagy's video presentation of this sample application, which demonstrates how Adobe AIR for Android can benefit enterprise users with a highly dynamic employee directory app that works equally well across desktop and mobile.

Parsley overview

To create this application we used the Parsley framework. We'll go over a quick overview of Parsley, but this is not ment to be a tutorial on Parsley. For more information refer to the documentation.

Parsley is an application framework for Flex/AIR that offers several features including dependancy injection and a robust messaging framework. In order to take advantage of the dependancy injection and messaging features you must construct a Context. The Context contains an instance of all classes that are exposed to the messaging framework and are available to be injected into other classes. This can be seen in the following snippet found in EmpdirDesktop.mxml.

<fx:Declarations> <spicefactory:ContextBuilder> <spicefactory:FlexConfig type="{ApplicationContext}"/> <spicefactory:FlexConfig type="{EmployeeContext}"/> </spicefactory:ContextBuilder> </fx:Declarations>

If you examine the contents of the com.adobe.empdir.ApplicationContext and com.adobe.empdir.EmployeeContext classes, you'll notice that they contain various Command classes, Presentation Models, and other Manager classes. These classes and their functionality will be explained in more detail throughout the article. For now the important part to take away from this is that the Context contains a single instance of each of the classes referenced in either the ApplicationContext or EmployeeContext classes. Any class in the Context can be injected into any other class also found in the Context. An example of this can be seen in the PanelManager class:

[Inject] public var leftPanelPM:LeftPanelManagerPM;

Both the PanelManager class and the LeftPanelManagerPM class are found in ApplicationContext.mxml and can be injected when needed.

The second part, the messaging system, allows classes in the Context to communicate through ManagedEvents. ManagedEvents have three parts to them; the event being dispatched, the ManagedEvents metadata tag on the class dispatching the event, and the MessageHandler metadata tag on the receiving function. All managed events must be bubbled up to the Context which lives in the root of the application. The ManagedEvents metadata tag is placed on the class that is dispatching an event and sets the type that should be passed to the messaging framework. An example of this can be seen in the ApplicationHeaderPM class:

Note: Only key parts of the class are shown.

[ManagedEvents(names="search, changeState, openState, setSearchListFocus")] public class ApplicationHeaderPM extends EventDispatcher { . . . dispatchEvent(new SearchEvent(SearchEvent.SEARCH, pendingTerm)); . . . }

The MessageHandler metadata tag is the receiving end of the previous example. It defines the function to be called based on a selector and event type. An example of this can be found in the SearchResultsPanelPM class.

[MessageHandler(selector="search")] public function onSearch(event:SearchEvent):void{ currentState = SEARCHING_STATE; }

The selector criteria matches the event type that was dispatched in the ApplicationHeaderPM and the event:SearchEvent identifies that it is a SearchEvent type that has to be passed in.

This should cover the concepts of creating a Context, injecting classes, and the messaging framework which are key to understanding this article and sample code. If you are interested in more information about the Parsley framework, please visit the Parsley site.

Package structure

A well laid-out project structure helps you maintain code and keep it organized. We've decided to divide our applications into three types of projects: shell projects, domain projects, and library projects.

  • Shell projects: Shell projects exist on a one per screen basis. They are responsible for initializing the application, housing the corresponding views for that screen, and managing their states.
  • Domain projects: One way to keep your project organized is to group domain specific objects, that is to say objects that are all related to the same subject, together in their own project. Since these are grouped together into their own Flex library projects, it presents the opportunity for them to be used across multiple applications.
  • Library projects: These contain all the shared assets, events, skins, and components that are to be shared across shell and domain projects.

How we implemented it

The following is a quick rundown of our package structure, what is found where, and how it all ties together.

The Shell projects

empdir-mobile-shell
  • Responsible for managing all views specific to mobile.
  • Contains business logic specific to mobile.
  • Contains some custom mobile specific code (Android-like menu ).
empdir-desktop-shell
  • Responsible for managing all views specific to desktop.
  • Contains business logic specific to desktop.
  • Contains some specific desktop code—tray icon, dock icon, auto-update code (not in sample code).

The Library projects

empdir-library
  • Contains all the shared assets, skins, events, interfaces.

empdir-employee

  • Contains everything required for looking up and displaying employee information. For example, business logic, UI components, and presentation models specific to looking up and displaying employee information for any screens.

Skinning and styling

In the sample application we take two different approaches in reusing skin classes between multiple screens. One method uses a combination of FXG and CSS, whereas the other uses several different images and CSS. Each of these has advantages and disadvantages. The FXG approach allows the vector to be scaled for the various screens. However, FXG component images do incur a small performance hit (mainly on mobile devices). The alternative—using several different images and CSS—does not have these performance issues; however, it becomes harder to manage as the amount of screens you are targeting increases. You are forced to have a custom graphic for each screen due to scaling and resolution issues. You should use discretion when choosing between the two—large amounts of FXG component (especially animations and transformations) will have a noticeable performance impact on mobile devices.

How we implemented it

In our sample application we've implemented both FXG component and the use of images and CSS.

We'll start with covering how to define FXG component. Consider the following:

<icons:MagnifingGlass left="7" top="8" scaleX="{getStyle('searchIconScale')}" scaleY="{getStyle('searchIconScale')}"/>

The code snippet above is found in SearchInputSkin.mxml. The <icons:MagnifingGlass..> tag references the FXG image of the magnifing glass in the search input. Note that the two scaleX and scaleY properties both reference externalized values loaded from the style sheet. On mobile, these values are set to 2 which indicates to scale the vector to twice its X and Y values (basically double in size) whereas on destkop, we set the scale to 1 (unchanged). We mentioned previously the potential performance hit you may incur on mobile devices with FXG component. To help alleviate some of these performance problems, try not to overload your application with them and keep them static (no animations/transitions applied).

An alternative is to use CSS and multiple images for each screen. Consider the following:

<mx:Image id="closeButtonImage" source="{getStyle('closeNormal')}" mouseDown="closeButtonImage.source=getStyle('closePressed')" mouseOut="closeButtonImage.source=getStyle('closeNormal')"/>

and the two CSS files:

LightTheme.css ( Found in the mobile-shell project )

.searchInputSkin{ searchIconScale: 2.0; closeButtonRight: 5; closeButtonTop: 9; textPaddingLeft: 40; fontSize: 26; closeNormal: Embed('assets/icons/IconSearchCloseMobileNormal.png'); closePressed: Embed('assets/icons/IconSearchCloseMobilePressed.png'); }

LightTheme.css ( Found in the desktop-shell project )

.searchInputSkin{ searchIconScale: 1.0; closeButtonRight: 5; closeButtonTop: 6; textPaddingLeft: 26; fontSize: 16; closeNormal: Embed('assets/icons/IconSearchCloseNormal.png'); closePressed: Embed('assets/icons/IconSearchClosePressed.png'); }

The . searchInputSkin style is applied to the SearchInputSkin component. The closeButtonImage component uses the getStyle function to reference the externalized source from the CSS file. You'll notice that the image that is referenced in the LightTheme CSS changes based on the desktop and mobile environments. Externalizing the source values for the image allows the skin class to be reused across desktop and mobile.

It's worth mentioning that we didn't cover the use of 9-slice images in this article; they could be useful for an alternative way of skinning buttons and other components. However, this technique would not apply in all cases (for example, the above example could not have this technique applied to it); it would still require specific resolutions of that image per screen.

Presentation models and screen design

A presentation model is much like any other model—a class that contains variables that the view is bound too. However, the presentation model concept extends the traditional model to take the state and logic out of the view component. This concept lends itself well to multiscreen development as it allows you to have several view components laid out differently, and every component has a single class to handle the logic. These presentation models should be able to be shared most of the time between shell projects.

Personally, we don't recommend the reuse of views. Views and layouts should be tailored for the best experience on that screen. At times, that experience can be the same across all screens, but for the most part you will be building specific views for specific screens.

How we implemented it

Remember our project structure—the empdir-employee is a domain project that contains all of the shared presentation model classes for the employee related functionality. Consider the scenario detailed in Figure 1

The DepartmentPanel views are bound to the same shared DepartmentPanelPM.
Figure 1. The DepartmentPanel views are bound to the same shared DepartmentPanelPM.

Figure 1 illustrates how the separate DepartmentPanel views are bound to the same shared DepartmentPanelPM; the DepartmentPanelPM contains the state information as well as the logic for selecting a person or closing the panel. In both desktop and mobile the same thing needs to happen when an employee is selected from the the department panel. The panel manager needs to be notified to update and the loadEmployee event needs to be dispatched. The only thing that is different is the DepartmentPanel for mobile is laid out differently then the DepartmentPanel desktop. The same concept can be found in the AvailabilityPanel, DirectReportsPanel, and others.

Another thing to keep in mind is that you may want to use different touch-enabled components in the mobile app but not in the desktop app. Creating separate views for desktop and mobile allows you to do this while still reusing logic code (presentation model).

Commands and Events

For the most part, commands and events can be reused between screens. Events act as the communication piece to kick off commands and commands contain all the business logic, interface with external systems, local databases, and the file system. Most of the time, this business logic does not change across screens. However, there may be cases where the logic in the command may need to be altered for a specific screen. You can achieve this by instantiating the command class in the shell project's Context class and setting its properties from there. When the context is created, it will create an instance of the command you want to alter with new values for the public properties. From there, the command uses these values instead of the default values in the command.

How we implemented it

Take a look at the ApplicationContext.mxml files in both the empdir-desktop-shell and the empdir-mobile-shell . You'll notice that these files both instantiate a LoadDepartmentCommand , but on closer investigation you should also notice that the desktop version has the resultSize = -1 whereas the mobile version has resultSize = 20 . This doesn't limit the results returned from an employee seach for the desktop shell, but it does limit the results returned for mobile—despite it being the same Command class under the hood.

One imporant note about where the LoadDepartmentCommand is being added to the Context. Since we externalized some of the properties of this command to allow shell projects to supply specific values, this command has to be added to the Conext class that is built by the shell project. If this command was to be added to the Context by the empdir-employee – EmployeeContext.mxml , it would not be configurable from the individual shell projects.

Screen management

The experience you'll have on a desktop system, a mobile device, or a tablet can be drastically different. A desktop could have several windows, be resizable and display data in a completely different way from a single screen mobile view. To account for this we've taken the approach of designing a screen manager specific for each device. The ScreenManager class essentially controls displaying and updating the view states based on what needs to be shown. It does this by listening for state change events.

How we implemented it

Both desktop and mobile have separate screen manager classes. Each manager listens for the same state change events, however, they are handled differently. For example, when 'direct reports' is selected from the main employee view, a "show direct reports" event is dispatched and picked up from the Screen Manager class. In Desktop, this is handled by opening the "right panel" and showing the direct reports view in the right panel. Where as in mobile, the existing panel is swapped to the direct reports view. The same concept can be seen in availability view and department view.

You'll notice in PanelManager.as for the desktop shell that there is some desktop specific logic that is called when an employee is changed. In a desktop environment, you can be looking at an employee's details and their direct reports at the same time. If you were to change the selected employee, the panel manager needs to react to this and update the right panel to either show the direct reports of the newly selected employee or a No Direct Reports screen in place of it if they have none. In a mobile environment its not possible to to view both an employees details as well as their direct reports at the same time. Since updating the right panel is a screen specific function we put it into the panel manager.

Where to go from here

This article outlined the development techniques we've successfully used to deploy an internal enterprise application. We encourage you to try creating a multiscreen application of your own using the samples provided or apply the theory elements in this article to your preferred MVC framework. The Flex SDK "Hero" framework will introduce new best practices that will most likely affect the implementation details, however, the theory behind our techniques should remain similar.

Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License+Adobe Commercial Rights

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

More Like This

  • Generating a Windows installer for your AIR captive runtime application
  • Tips for building AIR applications that can be easily updated
  • Performance-tuning Adobe AIR applications
  • Getting started with Adobe AIR for Flex and ActionScript 3 developers
  • Using the Adobe AIR update framework
  • Adobe AIR and the experience brand
  • Introducing the Adobe AIR security model
  • Building Lupo: A case study in building commercial AIR applications
  • Using Badger for Adobe AIR applications
  • Developing cross-platform Adobe AIR applications

Tutorials and samples

Tutorials

  • Using the iOS Simulator to test and debug AIR applications
  • Using the Amazon In-App Purchase Adobe AIR native extension for Android and Kindle Fire
  • Transferring data with AIR native extensions for iOS – Part 3
  • Exchanging Vector and Array objects between ActionScript 3 and C, C++, or Objective-C

Samples

  • Licensing Adobe AIR applications on Android
  • Using web fonts with Adobe AIR 2.5
  • Using Badger for Adobe AIR applications

AIR blogs

More
07/09/2012 Protected: Publishing Adobe AIR 3.0 for TV on Reference Devices
07/08/2012 Source Code: Adobe AIR 3.3 Retina Video Application
07/06/2012 Application specific File Storage on Adobe AIR based ios Application
07/04/2012 Recent Work - iPad/Android App: Inside My toyota

AIR Cookbooks

More
02/09/2012 Using Camera with a MediaContainer instead of VideoDisplay
01/20/2012 Skinnable Transform Tool
01/18/2012 Recording webcam video & audio in a flv file on local drive
12/12/2011 Date calculations using 'out-of-the-box' functions

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement