Adobe
产品
Acrobat
Creative Cloud
创意套装
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
更多产品
解决方案
数字营销
数字媒体
教育
金融服务业
政府部门
网页体验管理
更多解决方案
学习帮助下载公司
商店
在线商店
批量许可
查找经销商
搜索
 
信息 登录
欢迎,我的支持
我的帐户
注销
为何登录?登录后可以管理您的帐户,访问试用版下载、产品扩展和社区区域等。
Adobe
产品 分类 购买   搜索  
解決方案 公司
学习
登录 注销 我的货物 我的支持
Date Date
Qty:
Subtotal
Checkout
Adobe 开发者中心 / Flex 开发人员中心 /

Flex移动性能检查列表

作者 Max Vujovic

Max Vujovic
  • maxvujovic.com

Content

  • ActionScript条目渲染器优化
  • MXML条目渲染器优化
  • 视图优化
  • 通用图形优化
  • 下一步阅读方向

Created

30 November 2011

页面工具

在 Facebook 上共享
在 Twitter 上共享
在 LinkedIn 上共享
书签
打印

Tags

要求

必备知识

本文要求基本了解 Adobe Flex编程知识。 本文适合那些希望编写自己第一款Flex移动应用程序并且正在寻求基本性能指南的初级和高级Flex用户。

用户级别

中级

必需产品

  • Flash Builder (Download trial)

本文将讨论你能够制定的用来保持你的Flex移动应用程序运行流畅的性能决策。 你能够采取用来确保获得卓越性能的唯一最重要的步骤是使用许多与Flex 4.6一起发行的高度优化的移动组件、皮肤以及条目渲染器(item renderer)并且以它们为基础建立其它组件。 使用这些组件并遵循本文中概述的一套最佳方法,你会在使用单一Flex编码基的 iOS、Android以及QNX设备上体验到高帧速率和快速加载时间带来的乐趣。

ActionScript条目渲染器优化

一个移动应用程序可能会包括数十个条目渲染器,并且当你的应用程序的确包括这么多条目渲染器时,对它们进行优化就变得很重要。 优化条目渲染器将会使你的应用程序在滚动过程中保持高的帧速率,这将给你的用户带来流畅、响应快速的体验。 Flex团队推荐你在ActionScript中编写条目渲染器以便于获得最佳的性能。 ActionScript条目渲染器与MXML条目渲染器相比编写的难度较大,然而相应的性能增益非常显著。 尽管MXML条目渲染器能够提供许多便利,其中包括状态语法(state syntax)、动态布局(dynamic layout)以及绑定表达式(binding expressions),然而ActionScript条目渲染器为了换取速度牺牲了这些便利。

子类LabelItemRenderer/IconItemRenderer

你可以通过利用ActionScript编写你的条目渲染器并建立高度优化的Flex LabelItemRenderer或者IconItemRenderer来改进相应的性能。 为了实现你的LabelItemRenderer或者IconItemRenderer子类,你可以覆盖条目渲染器的数据setter函数和createChildren、measure、drawBackground以及layoutContents方法。

为了开始创建一个能够扩展LabelItemRenderer以及覆盖这些方法的ActionScript模版,请遵循下面的这些步骤:

  1. 在Flash Builder 4.6中,选中File > New > Item Renderer。
  2. 输入你的条目渲染器的名称。
  3. 选中第二个标题为Custom ActionScript Item Renderer For Mobile List (ActionScript)的模版。
  4. 单击Finish。

相应的生成代码将包括一些注解,它们用来解释在每一个被覆盖的方法中需要做些什么。 如需获得每一个被覆盖的方法的更多详细的代码范例,请务必钻研各种相应的超级类(superclass)的方法。

如果你熟悉Flex组件生命周期,那么你可能注意到一个新的惯例:updateDisplayList已被分割成两个新的方法:drawBackground和layoutContents。 在LabelItemRenderer和IconItemRenderer中,updateDisplayList先调用drawBackground,其次再调用layoutContents。

图1显示了一个简单的显示股票行情符号以及它们值的变化的ActionScript条目渲染器的范例。

图1. StockRenderer条目渲染器
图1. StockRenderer条目渲染器

StockRenderer类能够扩展LabelItemRenderer,它使用一个自定义背景,并创建一个额外的StyleableTextField以便用于显示股票值的变化。 下面是相应的代码:

public class StockRenderer extends LabelItemRenderer { private const PADDING:Number = 20; private const GAP:Number = 40; private var change:Number; private var changeLabel:StyleableTextField; public function StockRenderer() { super(); } override public function set data(value:Object):void { super.data = value; change = (data ? data.change : 0.0); changeLabel.text = (change > 0 ? "+" : "") + change.toString(); invalidateDisplayList(); } override protected function createChildren():void { super.createChildren(); if (!changeLabel) { // Create a StyleTextField to display the stock's change value, and add it to the display list. changeLabel = StyleableTextField(createInFontContext(StyleableTextField)); changeLabel.styleName = this; changeLabel.editable = false; changeLabel.selectable = false; changeLabel.multiline = false; changeLabel.wordWrap = false; addChild(changeLabel); } } override protected function measure():void { // Determine the item renderer's desired width and height. measuredWidth = PADDING + labelDisplay.getPreferredBoundsWidth() + GAP + changeLabel.getPreferredBoundsWidth() + PADDING; measuredHeight = PADDING + Math.max(labelDisplay.getPreferredBoundsHeight(), changeLabel.getPreferredBoundsHeight()) + PADDING; measuredMinWidth = measuredWidth; measuredMinHeight = measuredHeight; } override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void { // Choose green or red for the background color based on the stock's change value. var backgroundColors:Array = (change >= 0 ? [0x00CC00, 0x009900] : [0xCC0000, 0x990000]); // Create a matrix to rotate the background gradient 90 degrees. var matrix:Matrix = new Matrix(); matrix.createGradientBox(unscaledWidth, unscaledHeight, Math.PI / 2, 0, 0); // Draw the gradient background. graphics.beginGradientFill(GradientType.LINEAR, backgroundColors, [1.0, 1.0], [0, 255], matrix); graphics.drawRect(0, 0, unscaledWidth, unscaledHeight); graphics.endFill(); } override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void { // Position labelDisplay against the left edge, and vertically align it. var labelDisplayX:Number = PADDING; var labelDisplayY:Number = (unscaledHeight - labelDisplay.getPreferredBoundsHeight()) / 2; setElementPosition(labelDisplay, labelDisplayX, labelDisplayY); // Position changeLabel against the right edge, and vertically align it. var changeLabelX:Number = unscaledWidth - changeLabel.getPreferredBoundsWidth() - PADDING; var changeLabelY:Number = (unscaledHeight - changeLabel.getPreferredBoundsHeight()) / 2; setElementPosition(changeLabel, changeLabelX, changeLabelY); } }

当在条目渲染器中显示图像时,使用子类IconItemRenderer

在内部,IconItemRenderer使用Flex ContentCache类来高速缓存外部下载的图标图像。 这意味着当用户向下滚动一个包含IconItemRenderers的列表时,从服务器加载外部的图像将会耗费一点时间,然而当用户反向向上滚动时,图像会立即出现,因为它直接来自IconItemRenderer缓存器。

使用StyleableTextField而非Label或者RichText来显示文本

StyleableTextField在渲染文本方面与Label或者RichText相比速度更快,因此在ActionScript条目渲染器中一直都是使用它来显示文本。 注意,StyleableTextField只能在ActionScript中使用,因此你不能在MXML条目渲染器或者MXML视图中使用它。

MXML条目渲染器优化

在ActionScript中编写条目渲染器将会获得最佳的性能。 但是,你仍可以使用MXML条目渲染器来获得相似的性能水平,然而你需要小心地使用下面的优化措施来调整它们。

保持你的条目渲染器的外观处于静态状态并小心使用cacheAsBitmap

cacheAsBitmap属性能够对性能产生积极或消极影响,这取决于它的使用方式。 如果一个条目渲染器的内部外观不经常改变,那么仅仅将cacheAsBitmap设置为true即可。 当条目渲染器的外观保持不变并且只有它的位置发生变化时,运行时能够快速地在它的新位置中重新绘制条目渲染器的缓存位图。 但是,条目渲染器的内部外观每发生一次改变,运行时都必须重新创建一张位图,这将会花费一些时间并对性能造成损害。

相同的情形也会发生在所有的组件上,而不仅仅只发生在条目渲染器上。 例如,千万不要在List上设置cacheAsBitmap。 在滚动时每一帧的List组件的内部外观均会改变,这将要求每一帧的运行时均重新产生许多多余的位图,从而显著降低帧速率。

如需了解更多关于cacheAsBitmap的信息,请查看Glenn Ruehle在他的47分钟的演说建立Flex Tablet应用程序的最佳方法(Best Practices for Building Flex Tablet Applications)中对正确使用cacheAsBitmap的解释。

保持你的条目渲染器的矩形形状及不透明状态并设置opaqueBackground

不像cacheAsBitmap那样,如果不当使用将容易损害性能,而opaqueBackground却只会改进性能。 但是,你的条目渲染器必须是矩形形状并且不透明以便于正确地进行渲染。

在系统内部,opaqueBackground属性能够指示运行时使用一个高度优化并且能够忽略透明度计算(transparency calculation)的渲染路径。

为了使用opaqueBackground属性,你需要在一个条目渲染器上将它设置为一个特定的颜色。 即使你为opaqueBackground设置一个单一颜色,你仍然能够使用另外一种自定义不透明的背景完全地覆盖住该颜色并且获得性能上的优势。

下面是一个简单条目渲染器,它能够设置opaqueBackground以便获得性能增益,并且在一个梯度填充(gradient-filled )的Rect的纯色背景中完美地进行绘画操作:

<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" cacheAsBitmap="true" opaqueBackground="0xFF0000" autoDrawBackground="false"> <s:Rect left="0" right="0" top="0" bottom="0"> <s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry color="#FFFFFF" ratio="0"/> <s:GradientEntry color="#DDDDDD" ratio=".33"/> <s:GradientEntry color="#999999" ratio=".66"/> </s:LinearGradient> </s:fill> </s:Rect> <s:Label id="labelDisplay" left="5" right="5" top="15" bottom="15"/> </s:ItemRenderer>

如果你绘制你自己的背景,那么你需要关闭autoDrawBackground

如果你按照之前代码范例中使用的方式在你的条目渲染器中定义一个背景Rect,那么你应该关闭autoDrawBackground。 这一操作将会指示Flex不要浪费时间来绘制一个你无论如何都会覆盖的默认背景。

使用Label而非RichText来显示文本

虽然StyleableTextField是显示文本最快速的组件,但是你仍然不能在MXML中使用它。 下一个你可以在MXML中使用的最快速组件是Label。 最为重要的是,你应该一直避免在你的应用程序中使用RichText,因为它不是用来优化移动设备的。

覆盖数据setter函数而非使用绑定表达式(binding expression)

在系统内部,绑定表达式(binding expression)能够调度事件并且运行额外的ActionScript代码。 复合绑定表达式(complex binding expression)和双向绑定表达式(two way binding expression)甚至更加冗长。 幸运的是,你可以方便地通过在一个已被覆盖的数据调 setter函数中更新条目渲染器的显示,以避免在条目渲染器中使用绑定表达式(binding expression)。

例如,你可以按照下面的方式覆盖条目渲染器的数据setter函数:

<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" cacheAsBitmap="true" opaqueBackground="0xFF0000" autoDrawBackground="false"> <fx:Script> <![CDATA[ override public function set data(value:Object):void { super.data = value; if (data) { nameLabel.text = data.name; phoneNumberLabel.text = data.phoneNumber; } else { nameLabel.text = ""; phoneNumberLabel.text = ""; } } ]]> </fx:Script> <s:Rect id="background" left="0" right="0" top="0" bottom="0" > <s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry color="#FFFFFF" ratio="0"/> <s:GradientEntry color="#DDDDDD" ratio=".33"/> <s:GradientEntry color="#999999" ratio=".66"/> </s:LinearGradient> </s:fill> </s:Rect> <s:Label id="nameLabel" left="5" right="5" top="15" bottom="15" fontSize="12"/> <s:Label id="phoneNumberLabel" left="5" right="5" top="30" bottom="15" fontSize="10"/> </s:ItemRenderer> The previous method is much faster than using binding in an item renderer like this: <?xml version="1.0" encoding="utf-8"?> <s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" cacheAsBitmap="true" opaqueBackground="0xFF0000" autoDrawBackground="false"> <s:Rect id="background" left="0" right="0" top="0" bottom="0" > <s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry color="#FFFFFF" ratio="0"/> <s:GradientEntry color="#DDDDDD" ratio=".33"/> <s:GradientEntry color="#999999" ratio=".66"/> </s:LinearGradient> </s:fill> </s:Rect> <s:Label id="nameLabel" value="{data.name}" left="5" right="5" top="15" bottom="15" fontSize="12"/> <s:Label id="phoneNumberLabel" value="{data.phoneNumber}" left="5" right="5" top="30" bottom="15" fontSize="10"/> </s:ItemRenderer>

前面的方法与在条目渲染器中使用绑定的方法相比速度要快得多,如下所示:

<?xml version="1.0" encoding="utf-8"?> <s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" cacheAsBitmap="true" opaqueBackground="0xFF0000" autoDrawBackground="false"> <s:Rect id="background" left="0" right="0" top="0" bottom="0" > <s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry color="#FFFFFF" ratio="0"/> <s:GradientEntry color="#DDDDDD" ratio=".33"/> <s:GradientEntry color="#999999" ratio=".66"/> </s:LinearGradient> </s:fill> </s:Rect> <s:Label id="nameLabel" value="{data.name}" left="5" right="5" top="15" bottom="15" fontSize="12"/> <s:Label id="phoneNumberLabel" value="{data.phoneNumber}" left="5" right="5" top="30" bottom="15" fontSize="10"/> </s:ItemRenderer>

当在你的条目渲染器中显示外部图像时,使用共享的ContentCache

如果你需要将外部图像下载到条目渲染器中,那么你应该不会希望每次当数据条目在视图中滚进滚出时都重新下载它们。 正如之前提到的那样,ActionScript IconItemRenderer使用一个 ContentCache来使得你的应用程序不必重新下载相应的组件。 通过声明一个静态的ContentCache实例并给它设置任一BitmapImage组件的contentLoader属性,你可以在你的MXML条目渲染器中进行相似的优化。 然后,该类型的所有条目渲染器将共享这个ContentCache实例,它将自动地加载并缓存你的图像。 这比它看起来还要简单一些,因此请参阅下面的代码范例:

<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" cacheAsBitmap="true" opaqueBackground="0xFF0000" autoDrawBackground="false" initialize="initializeHandler(event)"> <fx:Script> <![CDATA[ import mx.events.FlexEvent; import spark.core.ContentCache; static private const iconCache:ContentCache = new ContentCache(); private function initializeHandler(event:FlexEvent):void { icon.contentLoader = iconCache; } override public function set data(value:Object):void { super.data = value; if (data) { nameLabel.text = data.name; phoneNumberLabel.text = data.phoneNumber; icon.source = data.imageUrl; } else { nameLabel.text = ""; phoneNumberLabel.text = ""; icon.source = null; } } ]]> </fx:Script> <s:Rect id="background" left="0" right="0" top="0" bottom="0" > <s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry color="#FFFFFF" ratio="0"/> <s:GradientEntry color="#DDDDDD" ratio=".33"/> <s:GradientEntry color="#999999" ratio=".66"/> </s:LinearGradient> </s:fill> </s:Rect> <s:BitmapImage id="icon" top="10" left="5" width="32" height="32" /> <s:Label id="nameLabel" left="40" right="5" top="15" bottom="15" fontSize="12"/> <s:Label id="phoneNumberLabel" left="40" right="5" top="30" bottom="15" fontSize="10"/> </s:ItemRenderer>

为了定位组件,你需要使用BasicLayout或者ConstraintLayout,而非对Group容器进行嵌套。

你应该保持显示层级越浅越好。 将Group容器与VerticalLayout和HorizontalLayout的组合一起进行嵌套来创建复合布局将会产生许多不必要的布局代码。 相反,你可以考虑使用ConstraintLayout,或者通过使用诸如left、right、top以及bottom等BasicLayout约束条件来明确地指定组件的位置。 你可能已注意到,在代码范例中,我已经明确地指定了位置,而非使用嵌套的Groups或者动态布局。

假定用下面的三种方式来对ContactRenderer(参见图2)进行布局,它是一个MXML条目渲染器,用来显示个人的姓名和电话号码。

图2. 一个单一的ContactRenderer实例
图2. 一个单一的ContactRenderer实例

如下所示,你可以使用BasicLayout对ContactRenderer进行布局:

<s:BitmapImage id="icon" top="10" left="5" width="32" height="32" /> <s:Label id="nameLabel" left="40" right="5" top="15" bottom="15" fontSize="12"/> <s:Label id="phoneNumberLabel" left="40" right="5" top="30" bottom="15" fontSize="10"/>

你还能够以下面的方式使用ConstraintLayout:

<s:layout> <s:ConstraintLayout> <s:constraintColumns> <s:ConstraintColumn id="leftPaddingColumn" width="5"/> <s:ConstraintColumn id="iconColumn" width="32"/> <s:ConstraintColumn id="middleGapColumn" width="3"/> <s:ConstraintColumn id="textColumn" width="100%"/> <s:ConstraintColumn id="rightPaddingColumn" width="5"/> </s:constraintColumns> <s:constraintRows> <s:ConstraintRow id="topPaddingRow" height="10"/> <s:ConstraintRow id="firstRow" height="16"/> <s:ConstraintRow id="secondRow" height="16"/> <s:ConstraintRow id="bottomPaddingRow" height="10"/> </s:constraintRows> </s:ConstraintLayout> </s:layout> <s:BitmapImage id="icon" left="iconColumn:0" top="firstRow:0" width="32" height="32"/> <s:Label id="nameLabel" left="textColumn:0" right="textColumn:0" top="firstRow:5" fontSize="12"/> <s:Label id="phoneNumberLabel" left="textColumn:0" right="textColumn:0" bottom="secondRow:2" fontSize="10"/>

如下所示,最好通过嵌套Group组件来避免定位相应的元素:

<s:Group> <s:layout> <s:HorizontalLayout paddingLeft="5" paddingTop="10" paddingBottom="10" gap="3"/> </s:layout> <s:BitmapImage id="icon" width="32" height="32" /> <s:Group> <s:layout> <s:VerticalLayout gap="3" paddingTop="5" paddingBottom="5"/> </s:layout> <s:Label id="nameLabel" fontSize="12"/> <s:Label id="phoneNumberLabel" fontSize="10"/> </s:Group>

使用Group和FXG Graphics取代BorderContainer

BorderContainer是一个用来绘制具有边界和背景的容器的适宜组件,然而它并不适用于移动设备。 取而代之的是,你应该使用包含一个Rect的Group来获得相同的视觉效果。

如下所示,使用一个包含一个Rect的Group:

<s:Group width="200" height="200"> <s:Rect left="0" right="0" top="0" bottom="0"> <s:fill> <s:SolidColor color="#CCCCCC"/> </s:fill> <s:stroke> <s:SolidColorStroke color="#999999"/> </s:stroke> </s:Rect> <!-- Define child components here --> </s:Group>

如下所示,避免使用 BorderContainer:

<s:BorderContainer width="200" height="200" backgroundColor="#CCCCCC" borderColor="#999999"> <!-- Define child components here --> </s:BorderContainer>

视图优化

移动视图应该利用MXML编写。 不像条目渲染器那样,通常在某一时刻只有一个视图可见,因此,MXML的轻松使用要胜于ActionScript的性能优势。 无论如何,当你在不同的视图间进行切换时,你需要许多优化措施来确保你的应用程序运行顺畅并且响应快速。

覆盖数据setter函数,而非在creationComplete处理程序中使用绑定或者初始化View的外观

不要在creationComplete处理程序中初始化View的外观,因为这将会导致该视图再处理,这将推迟相应的视图转换。 取而代之的是,你需要在已被覆盖的数据setter函数中改变你的视图外观。 与使用条目渲染器的情形一样,覆盖相应的数据setter函数能够消除多余的绑定表达式(binding expression)。

在viewActivate中启动异步操作并在viewDeactivate中取消它们

服务器调用等异步操作可以在视图转换过程中返回,并且需要额外的运行代码,这可能会导致视图转换产生停顿现象。 最好在视图被转换到屏幕上之后,在viewActivate处理程序中启动异步操作。 你还应该考虑一下在切换视图前清除viewDeactivate处理程序中的一些未完成的异步调用。

有条不紊地初始化子组件

在开始进行视图转换之前,Flex需要创建并布局视图的所有子视图。 在开始阶段你应该尽可能保持视图的轻量级状态,以便最大程度地降低用户互动和视图转换开始时刻之间的延时。 如果可能,你应该在视图被转换到屏幕上之后逐渐地创建组件,但这一操作应该在viewActivate事件之后进行。 你必须避免创建在初始状态的视图中不可见的组件。

使用includeIn或者excludeFrom替代可见属性以便隐藏子组件

如果可能,使用includeIn和excludeFrom将不应该可见的组件从显示列表中删除。 这样能够避免对它们进行处理。 相反,如果你将 visible设置为false,那么组件将保留在显示列表上,这样需要执行不必要的布局操作和渲染过程。

为了在内存中保留视图,需要将destructionPolicy设置为"never"

如果用户经常切换回视图模式,那么你可能希望通过在内存中保留它以避免再一次创建它产生的成本。 但是,请记住在移动设备上,内存是稀缺的资源! 如果你放松对设备的RAM的限制,那么在内存中保留各种复杂的视图(或甚至保留太多简单的视图)将会降低其性能。

如下所示,为了通过使用更多内存来改善处理时间,你可以在View上将destructionPolicy设置为"never":

<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" title="My View" destructionPolicy="never"> <!-- define child components here --> </s:View>

通用图形优化

下面的优化措施会帮助你在你的应用程序中加速处理各种类型的图形,而不管这些图形是由条目渲染器、视图或者其它组件显示的。

创建图像的多个备份而非缩放它或者使用位图平滑处理技术(bitmap smoothing)

使用平滑处理技术来缩放图像看起来很好,然而这却要求提供很强的处理能力。 你应该以不同的尺寸创建多个版本的图像组件,而不是创建一个大的图像组件,然后将它根据不同的屏幕分辨率和DPI级别进行缩小。 查看Flex计算机科学家Jason San Jose的文章Flex移动皮肤—第二部分:处理不同的像素密度( Flex Mobile Skins – Part 2: Handling Different Pixel Densities),以便于了解提供各种最佳方法的详细教程。

使用预焙组件(prebaked asset)、文本加倍(text doubling)或RectangularDropShadow,而非过滤器

像大多数高质量的图像处理运算那样,Spark过滤器在移动设备上的计算量过于冗长,因此你应该避免使用它们,而选择其它技术。 在大多数情形下,你可以直接在你的图像组件中绘制一个阴影。 当处理文本时,你可以复制该文本并对它进行偏移以便创建一个阴影效果。 如果你希望获得一个落在矩形组件上的阴影,那么Flex能够为 DropShadowFilter提供一个名称为RectangularDropShadow的非常有效的替代品。 RectangularDropShadow不是过滤器,而是组件,你可以基本上像使用Rect一样使用它。

如下所示,使用RectangularDropShadow:

<s:Group width="200" height="200"> <!-- drop shadow --> <s:RectangularDropShadow left="0" right="0" top="0" bottom="0" distance="3" alpha="0.5"/> <!-- background and border --> <s:Rect left="0" right="0" top="0" bottom="0"> <s:fill> <s:SolidColor color="#DDDDDD"/> </s:fill> <s:stroke> <s:SolidColorStroke color="#999999"/> </s:stroke> </s:Rect> <!-- define child components here --> </s:Group>

如下所示,避免使用DropShadowFilter: 

<s:Group width="200" height="200"> <!—- drop shadow --> <s:filters> <s:DropShadowFilter distance="3" alpha="0.5"/> </s:filters> <!-- background and border --> <s:Rect left="0" right="0" top="0" bottom="0"> <s:fill> <s:SolidColor color="#DDDDDD"/> </s:fill> <s:stroke> <s:SolidColorStroke color="#999999"/> </s:stroke> </s:Rect> <!-- define child components here --> </s:Group>

使用BitmapImage而非Image进行图像嵌入操作

BitmapImage组件是一个轻量级版本的Image组件。 这两个组件都能够显示嵌入式的图像组件。 两者之间最大的差异是Image 能够即装即用加载外部图像,而BitmapImage需要一些设置才能加载外部图像。

与BitmapImage不同,Image的皮肤也是可换的并且支持丢失图像指示器。 对于嵌入图像,你不需要所有这些额外的功能,恰恰相反,你应该使用轻量级的BitmapImage组件。

如下所示,使用BitmapImage组件:

<s:BitmapImage source="@Embed('assets/icon.jpg')"/>

如下所示,避免使用Image组件:

<s:Image source="@Embed('assets/icon.jpg')"/>

使用PNGs,而非GIFs和JPEGs

运行时在对PNG文件格式进行解码时速度要快得多,因此无论在什么情况下,只要你有选择权,那么你都应该使用PNG来代替GIF和JPEG图像。

使用FXG文件绘制非平凡矢量图形(nontrivial vector graphic)

为方便起见,你应该使用MXML原语来绘制背景矩形等简单的矢量图像。 但是,对于更复杂的图形和矢量插图来说,你应该在Adobe Illustrator中或者相似的设计工具中创建FXG文件。 FXG文件由一个预编译的绘图指令序列组成,与大量在MXML中声明的原语来相比,FXG文件具有更快的执行速度并占用较少的内存。 如需了解更多关于 FXG与MXML图形对比的信息,请查看相应的FXG和MXML Graphics参考文章。

减少同步运行的效果数量

Flex能够提供Resize或Fade等效果,它们能够方便地为用户界面在响应触摸互动操作时提供动画效果。 最好应该限制一下在同一时刻运行的效果数量,这是因为就处理成本而言,它们会叠加在一起。

尽可能使用CSS样式,而非对组件重新植皮

通过使用CSS样式,你可以充分利用高度优化的默认Flex移动皮肤。 在大多数情形下,完全可以使用样式来定制你的UI组件的外观。 如需获取一些CSS样式的范例,请查看Holly Schinsky的文章设计你的Flex 4.5移动应用程序标签和工具栏的式样(Styling your Flex 4.5 Mobile Application Tabs and ActionBar)。

在创建自定义皮肤时,利用ActionScript扩展默认移动皮肤

如果CSS样式的数量不足,那么你可能会决定为某个组件编写一个自定义的移动皮肤。 你应该利用ActionScript 编写该皮肤并扩展相应的默认Flex移动皮肤以便充分利用它们的潜在的性能优化优势。 查看Jason San Jose关于移动植皮的系列文章,它们能够指导你了解相应的过程。

下一步阅读方向

在你的应用程序开发过程的每一个步骤中,你都需要确保完成你的性能目标。 不要让你自己指望其它功能,直到你满意你的应用程序在其当前阶段的性能。 声称“我稍后来修复它”可能是自负特征的第一个警告信号或者是一个不良架构选择。 解决这两个问题都应该宜早不宜迟。

在这篇检查列表中的许多优化措施都直接地来源于先前和现在的Flex SDK团队成员的精彩演讲,其中包括Evtim Georgiev、Steven Shongrunden、Glenn Ruehle以及Ryan Frishberg等。 我强烈建议对这些主题的更多细节感兴趣的每一个人都去看一下Adobe TV上的演讲:

  • Evtim Georgiev和 Steven Shongrunden的 性能-调试移动Flex 应用程序(Performance-Tuning Mobile Flex Applications)
  • Glenn Ruehle的创建移动Flex 平板电脑应用程序的最佳方法 (Best Practices for Building Mobile Flex Tablet Applications)
  • Ryan Frishberg的Flex和Flash开发的性能提升技巧(Performance Tips and Tricks for Flex and Flash Development )

Creative Commons License
本文基于Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License协议发布。

More Like This

  • 项目Hendrix:一个呼叫中心用户体验管理解决方案
  • 打造企业Flex团队
  • Finicky:用户自定义移动Flex应用
  • Flex mobile development tips and tricks – Part 5: Using mobile view and tab transitions
  • Migrating Flex 3 applications to Flex 4.5 – Part 4: Using Spark Panel, List, DataGrid, and VGroup components and adding custom skins and states
  • Adobe Flex 4.6 SDK介绍
  • 使用Flex 4.5 SDK和Flash Builder 4.5构建Web和移动参考应用程序
  • Migrating Flex 3 applications to Flex 4.5 – Part 2: Beginning migration of the Dashboard application to Flex 4.5
  • Migrating Flex 3 applications to Flex 4.5 – Part 3: Introducing Spark components and simple skins
  • Flex 4.6 SDK和Flash Builder 4.6中的新功能

Tutorials & Samples

Tutorials

  • Flex mobile performance checklist
  • Flex and Maven with Flexmojos – Part 3: Journeyman
  • Migrating Flex 3 applications to Flex 4.5 – Part 4

Samples

  • Twitter Trends
  • Flex 4.5 reference applications
  • Mobile Trader Flex app on Android Market

Flex User Forum

More
07/25/2011 Flash Player Debug Issues - Safari 5.1 & Chrome 13
04/22/2012 Loader png - wrong color values in BitmapData
04/22/2012 HTTPService and crossdomain.xml doesn't work as expected
04/23/2012 Memory related crashes in Flex application

Flex Cookbook

More
04/06/2012 How to detect screen resize with a SkinnableComponent
02/29/2012 Embed Stage3D content inside Flex application components
02/15/2012 Custom WorkFlow Component
02/09/2012 Using Camera with a MediaContainer instead of VideoDisplay

产品

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • 移动应用程序
  • Photoshop
  • Touch Apps

解决方案

  • 数字营销
  • 数字媒体
  • 网页体验管理

行业

  • 教育
  • 金融服务业
  • 政府部门

帮助

  • 产品帮助中心
  • 订货和退货
  • 下载和安装
  • 我的 Adobe

学习

  • Adobe 开发人员连接
  • Adobe TV
  • 培训和认证
  • 论坛
  • 设计中心

购买方式

  • 在线商店
  • 批量许可
  • 查找经销商

下载

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

公司

  • 新闻编辑室
  • 合作伙伴计划
  • 公司社会责任
  • 工作机会
  • 投资者关系
  • 事件
  • 法律
  • 安全
  • 联系 Adobe
选择您的地区 中国(更改)
选择您的地区 关闭

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.

使用条款 | 隐私政策和 Cookies (更新)

京 ICP 备 10217899 号 京公网安备 110105010404