Руководство по actionscript. часть 4, стр. 128
Во-вторых, не забывайте, что событие Event. RENDER возникает в том случае, когда любой объект — не обязательно текущий — вызывает метод stage. invalidate ( ). Таким образом, в текущем состоянии метод renderListener ( ) будет вызывать метод draw ( ) всякий раз, когда любой объект в приложении вызывает метод stage. invalidate ( ). В приложении с множеством объектов такая избыточность может привести к серьезным проблемам, связанным с производительностью.
Чтобы решить эти две оставшиеся проблемы, мы внесем последний набор изменений в класс Ellipse — добавим новую логику, позволяющую определить, требуется ли перерисовка эллипса при вызове методов addedToStageListener ( ) и renderListener ( ). Во-первых, добавим новую переменную экземпляра changed, которая будет сообщать о том, требуется ли перерисовка объекта El 1 ipse при очередном обновлении экрана. Затем, чтобы устанавливать и сбрасывать значение переменной changed, а также проверять ее статус, добавим три новых метода: setChanged( ), clearChanged ( ) и hasChanged( ). Наконец, всякий раз при изменении эллипса (то есть всякий раз при вызове метода setwidth ( ), setHeight ( ) или метода-конструктора) мы будем присваивать переменной changed значение true.
В листинге 23.5 представлена окончательная версия класса Ellipse с комментариями, которые помогут вам понять код (изменения выделены полужирным шрифтом). Как отмечалось ранее, класс, представленный в листинге 23.5, безусловно, является более сложным, чем его первоначальная, неоптимизированная версия из листинга 23.2. Однако в приложениях, требующих максимальной графической производительности, подход с отложенной визуализацией, применяемый в листинге 23.5, является просто незаменимым. Дополнительную информацию по классам, представляющим фигуры и использующим отложенную визуализацию, можно найти в гл. 25.
Листинг 23.5. Окончательная, оптимизированная версия класса Ellipse
package { import flash. display. Shape; import flash. events.*;
public class Ellipse extends Shape { private var wiNumber; private var h:Number; private var changed:Boolean;
public function Ellipse (width:Number, height:Number) { // Регистрируем приемники для получения уведомлений, когда данный // объект добавляется в список отображения или удаляется из него var StageDetector:StageDetector = new StageDetector(this); StageDetector. addEventListener(StageDetector. ADDED_TO_STAGE,
addedToStageLi stener); StageDetector. addEventLi stener(StageDetector. REMOVED_FROM_STAGE.
removedFromStageListener); // Устанавливаем ширину и высоту w = width; h = height;
// Помечаем, что объект изменился setChanged( );
}
public function setWidth (newWidth:Number):void { w = newWidth; setChanged( );
}
public function getWidth ( ):Number { return w;
}
public function setHeight (newHeight:Number):void { h = newHeight; setChanged( );
}
public function getHeight ( ):Number { return h;
}
// Помечает, что в данной фигуре что-то изменилось private function setChanged ( ):void {
changed = true;
if (stage!= null) { stage. invalidate( );
}
}
// Помечает, что самые последние изменения // были отображены на экране private function clearChanged ( ):void { changed = false;
}
// Сообщает о том, содержит ли данная фигура изменения, // которые еще не были отображены на экране protected function hasChanged ( ):Boolean { return changed;
}
// Приемник события вызывается при добавлении этой фигуры // в список отображения
private function addedToStageListener (e:Event):void { // Регистрируем приемник для получения уведомлений // об обновлениях экрана
stage. addEventLi stener(Event. RENDER, renderLi stener);
// Если за то время, пока объект отсутствовал в списке отображения,
// произошли какие-либо изменения, нарисуем эти изменения
// при следующей визуализации экрана. Однако если с момента,
// когда объект находился в списке отображения, никаких изменений
// не произошло, в его отрисовке нет необходимости, if (hasChanged( )). { stage. invalidate( );
}
}
// Приемник события вызывается при удалении этой фигуры из списка // отображения
private function removedFromStageListener (e:Event):void { // Нет необходимости в получении событий обновления экрана, когда // данный объект не находится в списке отображения stage. addEventLi stener(Event. RENDER. renderLi stener);
}
// Приемник события вызывается перед обновлением экрана, если был вызван
// метод stage. invalidate( )
private function renderListener (e:Event):void {
// Вызываем метод draw ( ), если изменения, внесенные в данную фигуру,
// еще не были отображены.