2010-12-12 5 views
6

JS 월드에서 AS3에 왔는데 익명의 기능이 내 약점이라는 것을 고백해야합니다. 나는 그들을 도처에 쓰는 경향이있다. 이제는 AS3에 와서 많은 곳에서 들었습니다. AS와 Flash는 가비지 수집을 처리 할 때 매우 좋지 않습니다. 즉, 이상한 설명 할 수없는 메모리 누수를 피하기 위해 수동으로 모든 이벤트 핸들러와 객체를 비우고 삭제해야합니다. 충돌. 이 부분이 사실인지 모르지만 처음부터 모범 사례를 따르고 싶습니다.익명 동작 스크립트의 이벤트 처리기로 기능 - 좋든 나쁘니?

내 질문에 - 얼마나 나쁜 이벤트 처리기로 익명의 기능을 사용하는 아이디어입니까? ,

addEventListener(Event.ENTER_FRAME, function() : void { 
    controls.elapsed = stream.time; 
}); 

떨어져 비디오 플레이어의 현재 재생 시간 설정에서 전체 UI를 업데이트 세터입니다 contorls.elapsed 및 스트림NetStream을 객체입니다 예를 들어이 같은 코드를 살펴 보자 실제 비디오를 스트리밍합니다.

익명의 기능으로 코드를보다 명확하고 직관적으로 만들 수있는 곳이 많이 있습니다. 간단한 페이드 인 효과를 컨트롤 바의 다음 코드 확인 : 나는 완전히 보이는하고 코드에 맞는 방법과 같은

public function showControls() : void 
    { 
     var self:Controls = this; 

     if (!visible) { 
      visible = true; 
      fadeTimer = new Timer(30, 10); 
      fadeTimer.addEventListener(TimerEvent.TIMER, function() : void { 
       self.alpha += 0.1; 
      }); 
      fadeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, function() : void { 
       self.alpha = 1; 
      }); 
      fadeTimer.start(); 
     } 
    } 

을,하지만 난 누출에 대한 걱정. Event.ENTER_FRAME 핸들러는이 형식에서는 결코 해를 끼치 지 않지만 타이머 리스너는 어떨까요? 해당 리스너를 수동으로 제거해야합니까, 아니면 자동으로 제거 되나요? fadeTimer = null? 익명 함수를 사용하는 리스너를 제대로 제거 할 수 있습니까?

+1

나는 익명의 기능을 제공하는 팬이 아닙니다. 하나는 추악하고 다른 곳에서는 코드를 중복시킬 수 없으며 마지막으로 성능과 메모리에 영향을 미치는 활성화 개체를 만듭니다. http://onflex.org/ACDS/AS3TuningInsideAVM2JIT.pdf – Allan

+3

성능과 메모리에 영향을주지 않는 요소가 AS에 있습니까? :) 글쎄, 내 익명의 기능은 유용합니다, 하나는 그 기능을 재사용하지 않아도, 클래스 정의를 어지럽히고 싶지 않아 한 장소에서 전체 논리를 유지하고 싶어. 이것은 내가 언제 어떻게 그것을 사용하는 경향이있다. 링크를 가져 주셔서 감사합니다, 나는 그것을 확인합니다. – jayarjo

+2

흠 ... "약간의 성능과 메모리에 미치는 영향"이 실제로 따옴표로 밝혀졌습니다. 이제는 어떤 성명서예요? "일부"는 무엇을 의미합니까? 이것이 그 의미에 의해 읽혀 진다면, "약간"은 사소한 가치처럼 들린다. 아니면 안돼? 얼마나 막연한가. – jayarjo

답변

2

작동하는 함수 방법을 사용할 때 아무 문제가 없습니다. 메모리 누출에 관해서는 스테이지에서 객체를 추적하여 객체를 제거 할 수 있는지 확인해야합니다. 상기 제어에 ENTER_FRAME 이벤트 핸들러는 추가

제어 익명 함수에 대한 참조를 갖는 것을 보장한다. 코드가 컨트롤의 일부이므로 컨트롤이있을 때 익명의 함수가 제거되므로 잘됩니다. 타이머에 이벤트 핸들러 추가

타이머가 익명 함수에 대한 참조를 갖는 것을 보장한다. 타이머가 실행중인 경우 익명 함수 참조를 유지하고 연관별로 Enture 제어를 유지합니다. 타이머가 정지되면 타이머와 타이머가 모두 수집되어야합니다.

다른 모든 방법이 실패하면 프로파일 러를 사용하여보십시오! ;)

+0

"수집해야"한다는 것은 자동으로 의미합니까? 또는 수동 dispose() 함수를 방해해야합니까? :) – jayarjo

+0

가비지 수집은 스윕을 수행 할 때 자동으로 제거해야 함을 의미합니다. –

+1

위의 코드에서 fadetimer는 결코 가비지 수집되지 않습니다. 명시 적 removeEventListener가 필요하거나 addEventListener를 useWeakReferences = false로 설정해야합니다. (스테이지에서 컨트롤을 제거해도 이벤트 핸들러가 제거되지 않습니다.) – ansiart

3

나는 이렇게 할 것입니다. 인터럽트되면 타이머를 지우려면 dispose()를 사용해야합니다.

private function showControls() : void 
{ 
    if(_isVisible) 
     return; 

    // start you control here 
    _fadeTimer = new Timer(30, 10); 
    _fadeTimer.removeEventListener(TimerEvent.TIMER, updateFade); 
    _fadeTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, updateFadeComplete); 
    _fadeTimer.start(); 
} 

private function updateFade(event : TimerEvent) : void 
{ 
    // update fade here 
} 

private function updateFadeComplete(event : TimerEvent) : void 
{ 
    dispose(); 
} 


private function dispose() : void 
{ 
    if(_fadeTimer) 
    { 
     _fadeTimer.stop(); 
     _fadeTimer.removeEventListener(TimerEvent.TIMER, updateFade); 
     _fadeTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, updateFadeComplete); 
     _fadeTimer = null; 
    } 
} 
+0

그런데 왜이 모든 것들이 도처에 펼쳐지는 것입니까? 그들은 코드의 어색함에 좀 더 가담합니까? – jayarjo

+2

죄송합니다. 그들은 개인 클래스 멤버이기 때문에. – Mattias

+3

@jayarjo - 밑줄 a는 개인 필드/변수의 이름을 지정하는 일반적인 규칙이지만 꼭 필요한 것은 아닙니다 –

7

그냥이 게시물에 주목 - 당신에게 사용 가능한 몇 가지가 있습니다. 하나는 arguments.callee (현재있는 함수에 대한 참조)입니다. 익명 함수에서 참조를 제거 할 때 유용합니다. 또한 이 addEventListener 코드에서 약한 참조를 사용할 수 있음을 알 수 있습니다. 그러나 익명 인 변수의 경우 GC'd가 바로 발생하므로이 함수는 작동하지 않습니다.단순함을 위해 다음과 같이 코드를 다시 작성했습니다. (작동해야 함 - 테스트하지 않았습니다)

private function showControls() : void { 

    if (visible) { 
     return; 
    } 

    var self:DisplayObject = this; 

    var fadeTimer= new Timer(30,10); 
    var handler = function(e:Event) { 

     switch (e.type) { 

      // timer complete 
      case TimerEvent.TIMER_COMPLETE: 

       // remove references to this anonymous function -- for garbage collection 
       fadeTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, arguments.callee); 
       fadeTimer.removeEventListener(TimerEvent.TIMER, arguments.callee); 

       // break out 
       return self.alpha = 1; 

      // timer 
      case TimerEvent.TIMER: 
       return self.alpha += 0.1; 

     } 
    } 

    fadeTimer.addEventListener(TimerEvent.TIMER, handler); 
    fadeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, handler); 
    fadeTimer.start(); 

} 
+0

와우, 정말 멋지 네요! 그것은 매우 인기있는 연습이었을 것입니다. 맞습니다. 정말로 일을합니까? 테스트 했습니까? 숨겨진 경고가 있습니까? – jayarjo

+1

숨겨진 경고는 권장 사항이 아닙니다. 나는 며칠 전에 테스트를 수행했습니다. 괜찮 았는데, 여전히 "위대한"옵션으로 보지는 않지만 클래스 멤버가 가장 좋은 방법이라고 생각합니다. 특성 개체를 찾아야합니다. 기본적으로 플래시를 허용하는 숨겨진 내부 개체입니다 회원들의 빠른 검색을 할 수 있습니다. 이벤트 처리를 좀 더 쉽게하기 위해 스위치 이벤트와 함께 많은 수의 핸들러를 뭉개보고 싶다. 이런 종류의 코드는 단지 유틸리티 클래스를 만들 것을 요구하고 있습니다. – ansiart

관련 문제