[AS]リスナー関数の弱参照について
避けて通ってきたところを理解できた(気がする)のでメモ。
リスナー関数を弱参照にする場合は、addEvenListener()の第5引数をtrueとする。
//例 //第5引数のデフォルト値はfalse this.addEventListener(Event.ENTER_FRAME, this.enterFrameHandler,false,0,true);
trueを設定することでリスナー関数は弱参照となりガベージコレクション(GC)の対象となる。
※弱参照とGCについては偉い人のサイトがわかりやすいです。
イベントリスナ (AS3) とガーベジコレクション:akihiro kamijo
Tweenのアニメーションが途中で止まる:FumioNonaka.com
はまったのはここで弱参照となるリスナー関数の状態。
どういうことかというと・・・
以下の処理ではリスナー関数が弱参照でGCが発動した際にenterframe処理は停止。
これは認識どおり。
//フレームアクション //GCが発動するとhogeの出力が止まる。 this.addEventListener(Event.ENTER_FRAME, function(e:Event):void{trace("hoge");},false,0,true); //※もちろん、第五引数をfalseにした場合はenterframe処理はGCが発動しても動き続ける。
でも以下のように書いた場合は、第五引数をtrueにしてあってもenterframe処理はGCが発動しても動き続ける。
//フレームアクション //GCが発動してもhogeは出力され続ける。 this.addEventListener(Event.ENTER_FRAME, this.enterFrameHandler,false,0,true); function enterFrameHandler(e:Event):void{ trace("hoge"); }
なんで???参照きれて破棄されるんじゃないのと思ったら・・・
リスナー関数:enterFrameHandlerの自身の参照がthisに残っているから破棄されないということらしい。
なのでこう書けば破棄される。
//フレームアクション //GCが発動でhogeの出力は止まる。 function init(){ this.addEventListener(Event.ENTER_FRAME, this.enterFrameHandler,false,0,true); //関数init内にenterFrameHandlerを定義することでローカル関数となる。 function enterFrameHandler(e:Event):void{ trace("hoge"); } } init();
ちなみにこれではだめ。
//フレームアクション //GCが発動でもhogeの出力が止まらない。 function init(){ this.addEventListener(Event.ENTER_FRAME, this.enterFrameHandler,false,0,true); } //関数initの外にenterFrameHandlerを定義することで関数自身の参照が保持される。 function enterFrameHandler(e:Event):void{ trace("hoge"); } init();
ようするに。。。
第五引数をtrueにしても、弱参照になるのは、addEventLisner()とリスナー関数の関係性、と。
リスナー関数自身の参照が残ってる場合はtrueにしてもそれが残って破棄されない、と。
なんとなく、わかったような。。。
リスナー関数自身の参照も残らないようにしないといけないということらしい。
Tweet