创建用于移动设备的Flash内容
要为移动设备创建 Flash 内容,请遵循一些基本原则。例如,Flash 开发人员通常会避免使用特别复杂的图稿以及过多的补间或透明度效果。
由于各种移动设备的性能各不相同,因此 Flash Lite 开发人员还面对更多的挑战。如果必须将内容发布到多种不同的设备,开发人员有时不得不针对最基本的共同特性进行创作。
优化移动内容需要对各方面进行平衡。例如,一种技术可以使内容更美观,而另一种技术可以获得更好的性能。在评估这些平衡点时,您将需要来回地在模拟器中和目标设备上反复进行测试。您必须在实际设备上查看内容,以便对颜色真实性、文本可读性、物理交互、用户界面响应能力和真实移动体验的其它方面进行评估。适用于移动设备中的动画的 Flash Lite 准则
当创建用于移动设备的动画内容时,请牢记设备的 CPU 限制。遵循这些准则有助于避免 Flash Lite 内容运行缓慢:
在创建新的 Flash Lite 文件时,请检查文档是否已正确设置。虽然 Flash 文件可以平滑缩放,但是,如果该文件没有按照其本地舞台大小运行而必须在播放器中进行缩放,则会导致性能降低。请尝试设置文档的舞台大小以匹配目标设备的分辨率。同时将 Flash Player 设置为正确的 Flash Lite 版本,并在 Device Central 中选择一个合适的设备配置文件。
Flash Lite 可以按照低、中和高三种品质渲染矢量图形。渲染的品质越高,Flash Lite 渲染矢量图形时就越平滑和越精确,而且对设备的 CPU 的需求也越大。若要提供复杂的动画,应尝试更改播放器的品质设置,然后对 SWF 文件进行全面测试。若要控制 SWF 文件的渲染品质,请使用 _quality 属性或 SetQuality 命令。_quality 属性的有效值为 LOW、MEDIUM 和 HIGH。
限制同时发生的补间的数目。减少补间的数目或设置动画序列,以使一个动画在另一个动画结束时开始。
由于透明度 (Alpha) 效果需要占用大量 CPU 处理时间,因此对元件应适度使用透明度效果。尤其应避免对具有不完全不透明度(小于 100%)的 Alpha 级别的元件进行补间。
避免使用占用大量 CPU 处理时间的视觉效果,如大型蒙版、剧烈运动、Alpha 混合、大量渐变和复杂的矢量图形。
尝试组合使用补间、关键帧动画和 ActionScript 驱动的运动以生成运行效率最高的结果。
渲染矢量椭圆和圆形比渲染四边形更消耗内存。使用圆形和椭圆描边也会大大增加对 CPU 的使用。
经常在实际目标设备上测试动画。
当 Flash 绘制动画区域时,它会在该区域周围定义一个矩形定界框。尽量使该矩形最小以优化绘制。由于 Flash 会将合并区域解释为单一矩形,从而生成一个较大的整体区域,因此应避免重叠补间。使用 Flash 的"显示重绘区域"功能可以优化动画。
避免使用 _alpha = 0 和 _visible = false 以隐藏屏幕上的影片剪辑。如果您只是关闭影片剪辑的可视性或将其 Alpha 更改为零,则在线条渲染计算中仍会包括此影片剪辑,从而会对性能产生影响。
同样,请不要尝试通过将影片剪辑遮蔽在另一副图稿的后面来隐藏它。它仍将会包括在播放器的计算中。而是应该移动影片剪辑以使其完全脱离舞台,或通过调用 removeMovieClip 来删除这些影片剪辑。
移动设备中的 Flash Lite 位图和矢量图形
Flash Lite 可以对矢量图形和位图图形进行渲染。每种类型的图形都具有其自身的优点和缺点。有关使用矢量图形(而非位图图形)的决定并不总是显而易见的,通常取决于几个因素。
矢量图形在 SWF 文件中可用数学方程简洁地表示,并在运行时由 Flash Lite播放器渲染。相比之下,位图图形是以图片元素(像素)的数组表示,这需要更多字节的数据。因此,在文件中使用矢量图形可有助于减小文件大小和内存使用量。
矢量图形还可在进行大小缩放时保留其平滑形状。位图图像可以在进行缩放时以框状(或像素化)的形式显示。
与位图相比,矢量图形需要更多的处理能力来进行渲染,特别是包含许多复杂形状和填充的矢量图形。因此,大量使用矢量形状有时会降低文件的整体性能。由于位图图形进行渲染所需的处理时间比矢量图形少,因此对于某些文件而言,最好是选择位图图形(例如,要在移动电话上进行动画显示和滚动的复杂道路图)。
请牢记以下注意事项:
避免在矢量形状上使用轮廓。轮廓包含一个内边缘和一个外边缘(填充只有一个边缘),因此要对其渲染两次。
对角进行渲染要比曲线简单得多。如果可能,请使用平滑边缘(特别是非常小的矢量形状)。
优化对于小矢量形状(如图标)特别有用。复杂图标可能会在渲染时丢失细节,并浪费渲染细节的工作。
一条通用规则是,对较小的复杂图像(如图标)使用位图;较大的简单图像使用矢量图形。
按照正确的大小导入位图图形;不要导入较大的图形并在 Flash 中将它们缩小,因为这会浪费文件大小和运行时内存。
Flash Lite播放器不支持位图平滑。如果对位图进行缩放或旋转,它将具有短粗形外观。如果必须对图形进行缩放或旋转,可以考虑改为使用矢量图形。
文本实质上是一种非常复杂的矢量形状。当然,文本通常很重要,因此很少能够完全避免使用文本。如果必须使用文本,则应避免制作动画文本或将其放在动画上方。考虑将文本用作位图。对于多行动态和输入文本,将不会对文本字符串的换行符进行缓存。Flash 会在运行时换行,并在每次需要重新绘制文本域时重新计算换行次数。静态文本域不会有问题,因为在编译时已预先对换行进行了计算。对于动态内容,使用动态文本域是不可避免的,但是如果可能,应考虑改为使用静态文本域。
在 PNG 文件中应尽可能减少对透明度的使用;Flash 甚至必须计算对位图的透明部分进行的重绘。例如,对于表示前景元素的透明 PNG 文件,不要按照屏幕的完全大小导出透明 PNG, 而应按照前景元素的实际大小将其导出。
尝试分别将位图图层和矢量图层组合在一起。Flash 需要为位图和矢量内容执行不同的渲染器,而在渲染器之间进行切换需要花费一定的时间。
为用于移动设备的 Flash Lite 位图设置压缩
当使用位图时,可以设置用于减小 SWF 文件大小的图像压缩选项(既可以基于每个图像进行设置,也可以针对所有位图图像进行全局设置)。
设置单个位图文件的压缩选项
为所有位图图像设置压缩
选择"文件">"发布设置",然后单击"Flash"选项卡以显示压缩选项。
调整 JPEG 品质滑块或输入一个值。JPEG 品质值越大,生成的图像的品质越高,但也会生成更大的 SWF 文件。图像品质越低,生成的 SWF 文件就越小。请尝试使用不同的设置,以确定文件大小和图像品质之间的最佳平衡点。
优化用于移动设备的 Flash Lite 帧
大多数支持 Flash Lite 的设备以大约每秒 15 帧到 20 帧 (15-20 fps) 的速度播放内容。帧速率可以低至 6 fps。在开发过程中,请将文档的帧速率设置为接近目标设备的播放速度。这将显示内容在性能有限的设备上的运行情况。在发布最终 SWF 文件之前,请将文档的帧速率设置为至少 20 fps 或更高,以避免在设备支持更高帧速率的情况下限制性能。
当使用 gotoAndPlay 时,请记住,在 Flash 播放请求的帧之前,必须对当前帧和请求的帧之间的每个帧进行初始化。如果这些帧中的许多帧包含不同的内容,则使用不同的影片剪辑(而非时间轴)会更加有效。
虽然在桌面系统上通过将所有内容放置在文件的开始处来对其进行预载入是合理的,但在移动设备上进行预载入会延迟文件启动。请将内容安排在整个文件中,以便在使用影片剪辑时对其进行初始化。
为移动设备上的 Flash Lite 内容优化 ActionScript
由于大多数移动设备上都存在处理速度和内存的限制,因此,开发移动设备上使用的 ActionScript for Flash Lite 内容时应遵循下列准则:
使文件及其代码尽可能简单。删除未使用的影片剪辑、删除不必要的帧和代码循环并避免使用过多或无关紧要的帧。
使用 FOR 循环的成本可能很高,因为在每次迭代检查条件时,都会产生开销。如果迭代成本与循环开销不相上下,则应分别执行多次运算,而不是使用循环。代码可能较长,但性能会得到改善。
一旦不再需要基于帧的循环,应立即将其停止。
尽量避免字符串和数组处理,因为这类处理会占用大量 CPU 处理时间。
始终尝试直接访问属性,而不要使用 ActionScript getter 和 setter 方法(使用这两种方法的开销比使用其它方法调用的开销更大)。
合理地管理事件。在调用侦听器之前,通过使用条件来检查侦听器是否存在(不为 null),从而保持事件侦听器数组的紧凑性。通过调用 clearInterval 来清除任何活动间隔,并通过调用 removeListener 来删除任何活动侦听器之后,再使用 unloadapplication 或 removeapplicationClip 删除内容。在卸载影片剪辑时,如果任何 ActionScript 函数仍引用 SWF 数据,则 Flash 不会回收 SWF 数据内存(例如,从间隔和侦听器回收)。
当不再需要变量时,请将其删除或将其设置为 null,这会对其进行标记以便进行垃圾回收。由于删除变量的操作可从 SWF 文件中删除不需要的资源,因而有助于在运行时优化内存使用。删除变量比将变量设置为 null 更好。
在进行垃圾回收之前,可通过调用 removeListener 从对象中显式删除侦听器。
如果动态调用某个函数并传递一组固定参数,则应使用 call 来代替 apply。
使名称空间(如路径)更为紧凑以缩短启动时间。程序包中的每个级别将编译为一个 IF 语句并导致一个新的 Object 调用,因此减少路径中的级别可以节省时间。例如,具有 com.xxx.yyy.aaa.bbb.ccc.funtionName 级别的路径导致对象按照 com.xxx.yyy.aaa.bbb.ccc 进行实例化。一些 Flash 开发人员使用预处理器软件将路径简化成唯一的标识符(如 58923409876.functionName),然后再编译 SWF 代码。
如果文件由多个使用相同的 ActionScript 类的 SWF 文件组成,则在编译期间将从所选的 SWF 文件中排除这些类。这有助于缩短文件下载时间,并降低运行时的内存需求。
避免使用 Object.watch 和 Object.unwatch,因为每次更改对象属性时,都要求播放器确定是否必须发送更改通知。
如果在时间轴中的某个关键帧上执行 ActionScript 代码需要花费 1 秒多的时间才能完成,则可以考虑拆分此代码以便在多个关键帧上执行。
在发布 SWF 文件时,从代码中删除 trace 语句。为此,在"发布设置"对话框中的"Flash"选项卡上选中"省略跟踪动作"复选框。
继承会增加方法调用的次数并使用更多的内存:在运行时,包含其所需的所有功能的类比从超类中继承其部分功能的类具有更高的效率。因此在设计时,您可能需要在类的可扩展性和代码的效率之间找到一个平衡点。
如果一个 SWF 文件载入另一个包含自定 ActionScript 类(例如,foo.bar.CustomClass)的 SWF 文件并在稍后卸载该 SWF 文件,相应的类定义将保留在内存中。要节省内存,可显式删除已卸载的 SWF 文件中的任何自定类。请使用 delete 语句并指定完全限定的类名称,如:delete foo.bar.CustomClass。
限制对全局变量的使用,原因是在删除定义全局变量的影片剪辑之后,不会对这些全局变量进行标记以进行垃圾回收。
避免使用标准用户界面组件(在 Flash 的"组件"面板中提供)。这些组件是为在桌面计算机上运行而设计的,并未针对在移动设备上运行而进行优化。
尽量避免将函数嵌套太深。
避免引用不存在的变量、对象或函数。与 Flash Player 的桌面版本相比,Flash Lite 2 查找对不存在的变量的引用的速度较慢,这可能会对性能产生显著影响。
避免使用匿名语法定义函数。例如,myObj.eventName = function{ ...}。显式定义的函数具有更高的效率,例如 function myFunc { ...}; my Obj.eventName = myFunc;。
最大程度减少对 Math 函数和浮点数的使用。计算这些值会降低性能。如果必须使用 Math 例程,可以考虑预先计算这些值,并将其存储在变量数组中。在运行时,从数据表中检索这些值比让 Flash 计算这些值的速度要快得多。
管理用于移动设备的 Flash Lite 文件内存
Flash Lite 定期从内存中清除文件不再引用的所有对象和变量。这种操作称为垃圾回收。Flash Lite 每 60 秒运行一次垃圾回收进程,或者在文件内存使用量突然增加 20% 或更多时运行垃圾回收进程。
虽然您不能控制 Flash Lite 执行垃圾回收的方式和时间,但仍可以有意释放不需要的内存。对于时间轴或全局变量,可以使用 delete 语句来释放 ActionScript 对象使用的内存。对于局部变量(例如,在函数定义内定义的变量),不能使用 delete 语句来释放对象的内存,但可以将引用该对象的变量设置为 null。在不存在对该对象进行任何其它引用的情况下,这将释放该对象使用的内存。
以下两个代码示例说明了如何通过删除引用对象的变量来释放这些对象使用的内存。除了第一个示例创建的是时间轴变量,而第二个示例创建的是全局变量这一点区别之外,这两个示例完全相同。
// First case: variable attached to a movie or // movie clip timeline // // Create the Date object. var mcDateObject = new Date(); // Returns the current date as a string. trace(mcDateObject); // Delete the object. delete mcDateObject; // Returns undefined. trace(mcDateObject); // // Second case: global variable attached to a movie or // movie clip timeline // // Create the Date object. _global.gDateObject = new Date(); // Returns the current date as a string. trace(_global.gDateObject); // Delete the object. delete _global.gDateObject; // Returns undefined. trace(_global.gDateObject);
正如前面提到的那样,您不能使用 delete 语句来释放本地函数变量使用的内存, 而应将变量引用设置为 null,这与使用 delete 具有相同的效果。
function func() { // Create the Date object. var funcDateObject = new Date(); // Returns the current date as a string. trace(funcDateObject); // Delete has no effect. delete funcDateObject; // Still returns the current date. trace(funcDateObject); // Set the object reference to null. funcDateObject = null; // Returns null. trace(funcDateObject); } // Call func() function. func();
在 Flash Lite 中载入移动设备的数据
当开发用于移动设备的文件时,请最大程度地减少尝试一次加载的数据量。如果正在将外部数据载入 Flash Lite 文件中(例如,使用 XML.load),则当为传入的数据分配的内存不足时,该设备的操作系统可能会生成一个"内存故障"错误。即使剩余的内存总量足够,也会发生这种情况。
例如,假设某个文件试图加载大小为 100 KB 的 XML 文件,而设备的操作系统仅分配了 30 KB 的内存来处理传入的数据流。在这种情况下,Flash Lite 会向用户显示一个错误消息以指示内存不足。
若要加载大量数据,请将数据分组成一些较小的部分(例如,分组成若干个 XML 文件),然后进行多次数据加载调用以加载每个部分。每部分数据的大小和由此而需要进行的数据加载调用的次数将根据不同的设备和文件而不同。若要在数据请求次数和出现内存错误的可能性之间确定一个适当的平衡点,请在各种目标设备上测试文件。
为了获得最佳性能,应尽可能避免加载和解析 XML 文件。而是应将数据存储在简单的名称/值对中,并使用 loadVars 从文本文件中加载数据,或者从预编译的 SWF 文件中加载数据。
从 Flash Lite 的编译中排除类
要减小 SWF 文件的大小,请考虑从编译中排除类,但保留访问并使用它们进行类型检查的功能。例如,如果您正在开发使用多个 SWF 文件或共享库的文件,特别是在这些文件或共享库访问许多相同的类时,可以尝试此方法。排除类有助于避免重复这些文件中的类。