现在的位置: 首页 > 综合 > 正文

解析ActionScipt3在资源管理方面的特性和存在的问题

2013年10月03日 ⁄ 综合 ⁄ 共 2689字 ⁄ 字号 评论关闭

 在AS3中对资源管理影响最大的是其新引入的display list 模型。在flash8和其以前的版本中,当一个display object
移除后(用removeMovie
或unloadMovie),那么这个对象和其所有的子节点将会被立即从内存中删除,并且终止运行该对象的所有代码。Flash Player 9
引入了更灵活的display list 模型,把display objects(Sprites, MovieClips,
etc)看做一般的对象。这就意味着开发者可以做很多有趣的事情,比从新定义display object的容器(将一个display
object从一个display list移到另一个中),从已生成的swf文件中读取已实例化的display
object。不幸的是:这些display object将会被垃圾收集器等同于一般对象来处理。这就会引发一些潜在的问题。

  问题1:动态的内容

  其中一个比较明显的问题出现在与Sprite相关或其他容器的动态实例中,当你想要在某段时间后移除该对象时,Sprites(或其他容器)就
会出现一个比较明显的问题:当你从舞台(stage)上将其移除后,此时display object已经不在display
list上了,但事实上它仍然在内存中没有被清除。如果你没有清空这个剪辑的所有的引用或监听器,它可能用远也不会被从内存中删除。

  非常值得我们注意的是:display object不仅仅仍然占用着内存,而且它仍然在执行其内部的代码,例如Timer,enterFrames和其相关的外部监听器。

  现在有一个应用于游戏的sprite正在执行一个内部的enterFrame事件,每一帧它都会执行一些运算,并判断出它附近的其他游戏元素。
在AS3中,即使你将其从display
list中删除(removeChild)并且将其引用全部设置为null,在其被垃圾收集器回收之前,它将继续执行enterFrame内的代码。在删
除sprite之前,你必须明确:“enterFrame的监听器已经被删除”。

  假设有一个影片剪辑监听来自舞台的鼠标移动事件,在你移除其监听器之前,即使是该剪辑已经被删除(deleted),每有一次鼠标移动事件,其代码都会被执行,也就是这个剪辑将会被永远运行下去,作为一个来自舞台事件派发的引用。

  假设:在一些相互关联而且各自处于不同的状态的sprite(例如一些处于实例化,一些已经被删除),又或是在你删除对象前没能将其所有的引用
清空时。你可能不会发觉就是这个细节令你的cpu使用率直线上升,降低你的程序或者游戏的执行速度,或者使用户的电脑进入无响应状态。没有方法可以强制
flash播放器去立即删除一个display object并且停止其代码执行。你必须在从一个容器中删除一个display
object时手动的做一些处理。下一篇文章我将介绍对策。

  这里有一个例子(需要flash 9播放器),单击create(创建)
按钮来创建一个新的Sprite事例,Sprite将会带有一个计数器,并会显示出来。单击remove按钮并且观察计数器是怎么变化的,事实上
sprite的所以引用都已经被置空。你可以多创建几个实例来观察这个问题是如何让一个程序恶化的。

  问题2:加载的内容

  设想把加载的swf文件也同样当做一般的对象来对待,很容易想到一些你会遇到的问题。正如display objects一样,没有一种明确而有效的方法将swf的加载内容从内存中删除,或者立即停止其运行。置空其调用的Loader对加载的swf的所有引用,它最终还是会被GC(垃圾收集器)收集的。

  考虑2个这样的情景:

  1.你创建了一个shell
进行flash实验。这个实验是最前沿的,并且它会使cpu使用率到达最高。一个用户点击按钮加载了一个实验,观察后,又点击按钮加载了第二个实验。即使
是第一个的引用全部被清空,它仍然在后台运行,在第二个实验运行的同时,两个实验的负荷已经超出了cpu最大运算能力。

  2.一个客户要求你建立一个程序来读取其他开发者的swf文件。那些开发者给舞台添加了监听器,或者是用其他方法创建了一些指向swf内部的一
些引用。你现在没办法删除它的内容,直到关闭应用程序之前,它将一直在内存中并占用cpu。即使它们没有“内部引用”,它们也将继续执行下去,知道下一次
GC(垃圾收集器)将它们释放。

  出于项目安全的考虑,当你加载第三方内容时,你必须要了解的是:你是无法控制其删除或执行的。当一个swf被加载后,其很容易伴随你的程序一直在运行,即使是被删除了,当发生交互时被加载的swf可能会继续捕捉或干扰用户。

  问题3:时间轴

  在as3中时间轴是可以用代码来操作的。当执行播放时,它会动态的实例或删除display
object。这就意味着会遇到与问题一相同的问题。在某一帧虽然剪辑从舞台被删除,但是它仍然会继续保存在内存中,在被回收前,它会继续执行其内部的所
有代码。这不是程序员所期望的,当然也不是flash设计者所期望的。

  为什么会出现这个问题?

  Java开发者在看到这一问题时可能会说:“那又如何?”。这种差异是可以理解的,
flash开发人员并不习惯于手动干涉内存管理(因为以前就没这问题),而Java、C++的开发人员又已经习惯了强大的GC(无论是自动的还是手动
的)。这些问题是最新的内存管理语言自身带来的缺陷,不幸的是这些问题是无法被避免的。

  另一方面,Flash带来了很多在其他语言中罕见的问题(包括Flex中的一部分也是)。Flash内容中往往会有很多空闲或被动代码在被执
行,尤其是
java和Flex在交互时(通常来说:很多密集型运算都是和入户的输入紧密相连的)。Flash工程会更经常读取外部第三方内容(其代码质量通常是很差
的)。Flash
开发人员可利用的工具,资料和框架都比较少。而且据我所知负责开发flash的工作者的背景一般都是来自:音乐,艺术,商业,哲学或是其他的什么,但是除
了专业程序员。

  这种多元化的组合带来了令人惊奇的创造力和内容,但是他们并没有准备去讨论资源管理的问题。

  总结

  资源管理将会成为AS3开发的一个重要部分。忽略这一问题,可能会导致程序运行缓慢,或是完全的拖垮用户的系统。目前为止还没有明确的方法能立
即将display
object从内存中删除并停止其内部代码运行,这就意味这我们有责任去妥善的处理我们创造出来的对象。希望经过交流,可以探索出一个最佳的方法和框架来
更轻松解决这个问题。

抱歉!评论已关闭.