이 글을 읽기 전에 다음글을 먼저 참고하면 좋습니다.
이벤트 흐름도
자식 생성 체인 관계 (top-down)
부모객체의 childAdded() à child.initialize() à child.createChildren() à child.childAdded() à ... initialize() à ...createChildren()
최초 SystemManager에서 Application 객체에 대하여 childAdded(Application 인스턴스) 가 호출되어 체인으로 전파가 시작됩니다. 처음 가장 많이하는 실수가 stage, root, parent 에 대한 참조를 creationComplete 이벤트에서 얻으려 하는 것인데, applicationComplete 이벤트가 발생된 시점에서야 비로서 Application 객체에 stage, root, parent 속성이 모두 결정됩니다. 하지만 로딩한 swf가 있을 때 이swf 객체의 첫 번째 프레임은 아직 재생되지 않은 상태이므로 로드된 swf의 내부 객체를 참고하고 싶다면 callLater 를 통해 콜백함수를 예약하여 1프레임이 재생된 후 콜백 함수에서 처리하도록 합니다.
다음은 Framework에 제공된 소스를 분석하면서 관심 밖의 코드는 생략하고 주석을 달아본건데 위에서부터 차례로 쭉 읽어나가면 백마디 말보다 이해가 더 빠르리라고 생각됩니다.
{
public class UIComponent extends FlexSprite implements …
{
public function UIComponent()
{
super();
focusRect = false;.
tabEnabled = ( this is IFocusManagerComponent );
tabChildren = false;
enabled = true;
// initialized = true 일때 visible = true가 됨.
$visible = false;
addEventListener(Event.ADDED, addedHandler);
addEventListener(Event.REMOVED, removedHandler);
// focus, keyboard 이벤트 등록.
if ( this is IFocusManagerComponent ){
addEventListener(FocusEvent.FOCUS_IN, focusInHandler);
addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler);
addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
}
resourcesChanged();
resourceManager.addEventListener( Event.CHANGE, resourceManager_changeHandler, false, 0, true);
_width = super.width;
_height = super.height;
}
public function initialize():void
{
if ( initialized ) return;
// FlexEvent.PREINITIALIZE 이벤트 발생.
// 현재 컴포넌트 자신이 초기화가 완료된 후 parent메 attach되었었지만 아직 children이 생성되지는 않은 상태이다.
dispatchEvent(new FlexEvent(FlexEvent.PREINITIALIZE));
// Override로 구현하여 child객체를 생성하고 add 한다. (child 객체가 추가될때마다 childAdded() 메서드가 호출된다.)
createChildren();
// LayoutManager 객체에 속성값, 사이즈, 시각화 목록의 변경 상항을 각각의 메세지 큐로 보관한다.
childrenCreated();
// accessibility 생성, 초기화
initializeAccessibility();
// FlexEvent.INITIALIZE 이벤트 발생시킴.
initializationComplete();
}
// 부모객체의 childAdded() --> child.initialize() --> child.createChildren() --> child.childAdded() --> ...자식 생성 체인 관계
// 최초 SystemManager에서 Application 객체에 대하여 childAdded(Application 인스턴스); 가 호출되어 체인으로 전파가 시작된다.
// addChild, addChildAt 등의 메서드에서 호출되는 메서드
mx_internal function childAdded(child:DisplayObject):void
{
// child 객체의 initialize() 메서드 호출.
IUIComponent(child).initialize();
}
// LayoutManager 객체에 변경 사항을 저장
protected function childrenCreated():void
{
invalidateProperties();
invalidateSize();
invalidateDisplayList();
}
}
}
/** invalidateProperties(), invalidateSize(), invalidateDisplayList() 메서드는 각각 callLater 콜백함수를 통해 doPhasedInstantiation() 메서드를 호출한다. */
package mx.managers
{
public class LayoutManager extends EventDispatcher implements ILayoutManager
{
private function doPhasedInstantiation():void
{
// 단계별 객체 생성 여부 (default = false))
// 한번에 하나의 상황에 대해서만 처리
if ( usePhasedInstantiation ){
if ( invalidatePropertiesFlag ){
// commitProperties() 호출.
validateProperties();
// Preloader 가 청취하는 이벤트
ApplicationGlobals.application.dispatchEvent(new Event("validatePropertiesComplete"));
}else if ( invalidateSizeFlag ){
// measureSizes() 호출.
validateSize();
// Preloader 가 청취하는 이벤트
ApplicationGlobals.application.dispatchEvent(new Event("validateSizeComplete"));
}else if ( invalidateDisplayListFlag ){
// updateDisplayList() 호출.
validateDisplayList();
// Preloader 가 청취하는 이벤트
ApplicationGlobals.application.dispatchEvent(new Event("validateDisplayListComplete"));
}
// 세가지 상황에 대하여 모두 처리
}else{
// commitProperties() 호출.
if ( invalidatePropertiesFlag ) validateProperties();
// measureSizes() 호출.
if ( invalidateSizeFlag ) validateSize();
// updateDisplayList() 호출.
if ( invalidateDisplayListFlag ) validateDisplayList();
}
if ( invalidatePropertiesFlag || invalidateSizeFlag || invalidateDisplayListFlag ){
// 업데이트 할 내용이 남아있다.
callLaterObject.callLater(doPhasedInstantiation);
}else{
// 더이상 업데이트 할 내용이 없다
usePhasedInstantiation = false;
callLaterPending = false;
var obj:ILayoutManagerClient = ILayoutManagerClient(updateCompleteQueue.removeLargest());
while ( obj ){
// 처음 표시되는 상황이면 컴포넌트에서 FlexEvent.CREATION_COMPLETE 이벤트 발생 (initialized 변수에서...)
if ( !obj.initialized && obj.processedDescriptors )
obj.initialized = true;
// 속성, 사이즈 ,시각화 목록이 변경 될때 마다 컴포넌트에서 FlexEvent.UPDATE_COMPLETE 이벤트 발생.
obj.dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));
obj.updateCompletePendingFlag = false;
obj = ILayoutManagerClient(updateCompleteQueue.removeLargest());
}
// LayoutManager에서도 속성, 사이즈 ,시각화 목록이 변경 될때 마다 FlexEvent.UPDATE_COMPLETE 이벤트 발생.
dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));
}
}
}
}
정리하면...
'Blog > Flex' 카테고리의 다른 글
Flash CS4에서 폰트 임베딩 (5) | 2009.12.09 |
---|---|
move()와 x,y 속성, setActualSize() 메서드와 width, height 속성 (1) (4) | 2009.12.04 |
SystemManager에 대하여 (4) | 2009.11.25 |
stage, root에 대하여 (0) | 2009.11.24 |
Application의 컴파일에서 SWF가 실행될 때까지 (2) | 2009.11.20 |