弱参照のaddEventListenerのテスト

by kjkmr forked from ガベージコレクションの観察 (diff: 74)
addEventListenerしててもみんなガベコレされてるみたい
♥2 | Line 114 | Modified 2010-06-20 23:55:26 | MIT License
play

ActionScript3 source code

/**
 * Copyright kjkmr ( http://wonderfl.net/user/kjkmr )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/gtcf
 */

// forked from kjkmr's ガベージコレクションの観察
/*
addEventListenerしててもみんなガベコレされてるみたい
*/
package {
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.utils.Timer;
    import flash.events.Event;
    import caurina.transitions.Tweener;
    import flash.events.TimerEvent;
    import flash.system.System;
    import flash.display.BitmapData;
    import flash.utils.Dictionary;
    public class GarbageCollectionTest extends Sprite {
    	
    		private var _text:TextField = new TextField();
    		private var _timer:Timer = new Timer( 2000 );
    		private var _dic:Dictionary = new Dictionary( true );    
    		private var _dummySprite:Sprite;
    			
        public function GarbageCollectionTest() {
			GCChecker.init( this );
			GCChecker.addEventListener( GCEvent.GC, _onGC );
			
			//
			_timer.addEventListener( TimerEvent.TIMER, _onTimer );
			_timer.start();
			
			//
			_text.wordWrap = true;
			_text.width = stage.stageWidth;
			_text.height = stage.stageHeight;
			_text.text = "■開始\n\n";
			addChild( _text );
			
			//ローカル変数で適当なfunction
			var dummyHandler1:Function = function():void { _text.appendText("."); };
			var dummyHandler2:Function = function():void { _text.appendText("."); };
			
			//様々な種類のSpriteをDictionaryのキーに登録
			var s:Sprite;
			s = new Sprite();
			
			s.addEventListener( Event.ENTER_FRAME, dummyHandler1 );
			_dic[s] = "1. 普通にローカル変数のfunctionをaddEventListenerしたSprite";
			_dic[dummyHandler1] = "1. ローカル変数のfunction1";
			
			s = new Sprite();
			s.addEventListener( Event.ENTER_FRAME, dummyHandler2, false, 0, true );
			_dic[s] = "2. 弱参照:trueでローカル変数のfunctionをaddEventListenerしたSprite";
			_dic[dummyHandler2] = "2. ローカル変数のfunction2(弱参照で登録)";
			
			s = new Sprite();
			s.addEventListener( Event.ENTER_FRAME, _dummyHandler );
			_dic[s] = "3. 普通にクラスメンバのfunctionをaddEventListenerしたSprite";
			
			s = new Sprite();
			s.addEventListener( Event.ENTER_FRAME, _dummyHandler, false, 0, true );
			_dic[s] = "4. 弱参照:trueでクラスメンバのfunctionをaddEventListenerしたSprite";
			
			s = new Sprite();
			_dic[s] = "5. addEventListenerしてないSprite";
			
			s = new Sprite();
			_dic[s] = "6. クラスメンバに参照を保持したSprite";
			_dummySprite = s;
			
			//_dicの中身を表示
			_dumpDic();
        }
        
        /*--------------------------------------------------
        ダミーのイベントハンドラ
        --------------------------------------------------*/
        private function _dummyHandler( i_event:Event ):void {
        		_text.appendText(".");
        	}
        
        /*--------------------------------------------------
        メモリを無駄遣いするfunction
        --------------------------------------------------*/
        private function _wasteMemory():void {
        		//メモリをたくさんつかう。maxを100に設定すると毎回GCが走る
        		var max:uint = 100;
        		var b:BitmapData;
        		for ( var i:uint; i<max; i++ ){
	        		b = new BitmapData( stage.stageWidth, stage.stageHeight );
	        		b.draw(this);
        		}
        }
        
        /*--------------------------------------------------
        定期的にメモリを無駄遣いするためのTimerのハンドラ
        --------------------------------------------------*/
        private function _onTimer( i_event:TimerEvent ):void {
        		_text.appendText( "\n■Timer\n");
        		_wasteMemory();
        		//System.gc();//System.gcはDebugPlayerのみで有効らしい
        }
        
        /*--------------------------------------------------
        Dictionaryの中身をdump
        --------------------------------------------------*/
        private function _dumpDic():void {
        		_text.appendText( "【_dicの中身】\n" );
        		for each ( var item:* in _dic ) {
        			_text.appendText( item+"\n" );
        		}
        }
        
        /*--------------------------------------------------
        ガベージコレクション発生時のハンドラ
        --------------------------------------------------*/
        private function _onGC( i_event:GCEvent ):void {
        		_text.appendText( "\n■Garbages where collected!\n\n" );
			_dumpDic();
        }
    }
}


import flash.utils.Dictionary;
import flash.display.Sprite;
import flash.events.EventDispatcher;
import flash.events.Event;
import flash.display.DisplayObject;
 
class GCChecker {
	private static var _dummyDic:Dictionary = new Dictionary( true );
	private static var _dispatcher:EventDispatcher = new EventDispatcher();
	private static var _displayObject:DisplayObject;
	private static function _onEnterFrame( i_event:Event ):void {
		var cnt:uint = 0;
		var item:*;
		for each ( item in _dummyDic ) cnt++;
		if ( cnt ) return;
		dispatchEvent( new GCEvent( GCEvent.GC ) );
		_dummyDic[new Sprite()] = "dummy";
	}
    		
	public static function init( i_displayObject:DisplayObject ):void {
		_displayObject = i_displayObject;
		_displayObject.addEventListener( Event.ENTER_FRAME, _onEnterFrame );
		_dummyDic[new Sprite()] = "dummy";
	}
	
	public static function addEventListener( i_type:String, i_handler:Function ):void {
		_dispatcher.addEventListener( i_type, i_handler );
	}
	
	public static function removeEventListener( i_type:String, i_handler:Function ):void {
		_dispatcher.removeEventListener( i_type, i_handler );
	}
    		
	public static function dispatchEvent ( i_event:Event ):void {
		_dispatcher.dispatchEvent( i_event );
	}
}
    
class GCEvent extends Event {
	public static const GC:String = "gc";
	public function GCEvent( i_type:String, i_bubble:Boolean = false, i_cancelable:Boolean = false ) {
		super( i_type, i_bubble, i_cancelable );
	}
}