使用
REMOVED_FROM_STAGE
和
ADDED_TO_STAGE
事件正确冻结和解冻对象。
要优化您的代码,请始终冻结和解冻您的对象。冻结和解冻对所有对象都很重要,但对显示对象尤其重要。即使显示对象不再位于显示列表中并正在等待作为垃圾回收,其代码仍然占用大量 CPU。例如,它们仍然在使用 Event.ENTER_FRAME。因此,使用
Event.REMOVED_FROM_STAGE
和
Event.ADDED_TO_STAGE
事件正确冻结和解冻对象非常关键。以下示例显示一个在舞台上播放的、与键盘交互的影片剪辑:
// Listen to keyboard events
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyIsDown);
stage.addEventListener(KeyboardEvent.KEY_UP, keyIsUp);
// Create object to store key states
var keys:Dictionary = new Dictionary(true);
function keyIsDown(e:KeyboardEvent):void
{
// Remember that the key was pressed
keys[e.keyCode] = true;
if (e.keyCode==Keyboard.LEFT || e.keyCode==Keyboard.RIGHT)
{
runningBoy.play();
}
}
function keyIsUp(e:KeyboardEvent):void
{
// Remember that the key was released
keys[e.keyCode] = false;
for each (var value:Boolean in keys)
if ( value ) return;
runningBoy.stop();
}
runningBoy.addEventListener(Event.ENTER_FRAME, handleMovement);
runningBoy.stop();
var currentState:Number = runningBoy.scaleX;
var speed:Number = 15;
function handleMovement(e:Event):void
{
if (keys[Keyboard.RIGHT])
{
e.currentTarget.x += speed;
e.currentTarget.scaleX = currentState;
} else if (keys[Keyboard.LEFT])
{
e.currentTarget.x -= speed;
e.currentTarget.scaleX = -currentState;
}
}
单击“Remove”按钮后,将从显示列表中删除该影片剪辑:
// Show or remove running boy
showBtn.addEventListener (MouseEvent.CLICK,showIt);
removeBtn.addEventListener (MouseEvent.CLICK,removeIt);
function showIt (e:MouseEvent):void
{
addChild (runningBoy);
}
function removeIt(e:MouseEvent):void
{
if (contains(runningBoy)) removeChild(runningBoy);
}
即使将该影片剪辑从显示列表中删除,它仍会调度
Event.ENTER_FRAME
事件。影片剪辑仍在运行,但不会呈现。要正确处理这种情况,请侦听正确的事件并删除事件侦听器,以阻止执行占用大量 CPU 资源的代码:
// Listen to Event.ADDED_TO_STAGE and Event.REMOVED_FROM_STAGE
runningBoy.addEventListener(Event.ADDED_TO_STAGE,activate);
runningBoy.addEventListener(Event.REMOVED_FROM_STAGE,deactivate);
function activate(e:Event):void
{
// Restart everything
e.currentTarget.addEventListener(Event.ENTER_FRAME,handleMovement);
}
function deactivate(e:Event):void
{
// Freeze the running boy - consumes fewer CPU resources when not shown
e.currentTarget.removeEventListener(Event.ENTER_FRAME,handleMovement);
e.currentTarget.stop();
}
按下“Show”按钮后,将重新启动影片剪辑,它将再次侦听
Event.ENTER_FRAME
事件且键盘将正确控制该影片剪辑。
注:
如果将显示对象从显示列表中删除,则完成删除后将其引用设置为
null
不能确保该对象是冻结的。如果不运行垃圾回收器,则对象将继续占用内存和 CPU 处理,即使此对象不再显示。要确保对象占用的 CPU 处理最少,请确保在将其从显示列表中删除后完全将其冻结。
使用 Flash Player 10 和 AIR 1.5 启动时,还会发生以下行为。如果播放头遇到一个空帧,将自动冻结显示对象,即使没有实施任何冻结行为也是如此。
冻结的概念在使用 Loader 类加载远程内容时也很重要。在 Flash Player 9 和 AIR 1.0 中使用 Loader 类时,必须通过侦听由 LoaderInfo 对象调度的
Event.UNLOAD
事件来手动冻结内容。必须手动冻结每个对象,这是一项至关重要的任务。Flash Player 10 和 AIR 1.5 对 Loader 类引入了一个重要的新方法,称为
unloadAndStop()
。通过此方法,可以卸载 SWF 文件、自动冻结加载的 SWF 文件中的每个对象并强制运行垃圾回收器。
以下代码将加载 SWF 文件,然后使用
unload()
方法将其卸载,这需要更多的处理操作和手动冻结:
var loader:Loader = new Loader();
loader.load ( new URLRequest ( "content.swf" ) );
addChild ( loader );
stage.addEventListener ( MouseEvent.CLICK, unloadSWF );
function unloadSWF ( e:MouseEvent ):void
{
// Unload the SWF file with no automatic object deactivation
// All deactivation must be processed manually
loader.unload();
}
最好使用
unloadAndStop()
方法,该方法以本机方式处理冻结并强制运行垃圾回收过程:
var loader:Loader = new Loader();
loader.load ( new URLRequest ( "content.swf" ) );
addChild ( loader );
stage.addEventListener ( MouseEvent.CLICK, unloadSWF );
function unloadSWF ( e:MouseEvent ):void
{
// Unload the SWF file with automatic object deactivation
// All deactivation is handled automatically
loader.unloadAndStop();
}
调用
unloadAndStop()
方法时将执行下列操作: