Skip to content

Instantly share code, notes, and snippets.

@lynxerzhang
Created April 1, 2013 10:50
Show Gist options
  • Save lynxerzhang/5284263 to your computer and use it in GitHub Desktop.
Save lynxerzhang/5284263 to your computer and use it in GitHub Desktop.
package
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.IEventDispatcher;
import flash.utils.Dictionary;
/**
*
* 绑定事件监听的依据为指定根容器是否有显示对象移除, 如有移除, 则以此显示对象配置的事件监听一并清除
*
* TODO LIST
* 1.未考虑是否需要显示对象未添加至舞台时, 屏蔽事件回调
* 2.监测显示对象以强引用存入Dictionary, 是否需要以弱引用存入Dictionary, 即无任何引用时,
* 销毁改显示对象的同时, 清除所有对应监听
* @see http://code.google.com/p/asphalt2/ asphalt2.util.EventUtil
*/
public class LifeCircleStats
{
/**
* 设置指定显示对象主容器
* @param container
*/
public function LifeCircleStats(container:DisplayObjectContainer){
root = container;
root.addEventListener(Event.REMOVED, removedChildHandler);//handle by target phase or bubble phase
}
/**
* 当被移除的显示对象为指定根容器的子级或即为根容器时, 移除对应该显示对象配置的事件监听函数
* @param evt
*/
private function removedChildHandler(evt:Event):void{
var target:DisplayObject = DisplayObject(evt.target);
for(var item:* in check){
if(checkParent(item, target)){
check[item].forEach(forEachNode);
check[item] = undefined;
delete check[item];
}
}
}
private function forEachNode(node:Nd, ...args):void{
node.remove();
}
private var root:DisplayObjectContainer;
private const check:Dictionary = new Dictionary(false);
/**
* 添加监听, 并指定监测显示对象
* @param dispatcher
* @param type
* @param listener
* @param lifeCircleDisplay
*/
public function create(dispatcher:IEventDispatcher, type:String, listener:Function, lifeCircleDisplay:DisplayObject):void{
dispatcher.addEventListener(type, listener);
if(!check[lifeCircleDisplay]){
check[lifeCircleDisplay] = [];
}
check[lifeCircleDisplay].push(new Nd(dispatcher, type, listener, lifeCircleDisplay));
}
/**
* 移除指定显示对象监听函数
* @param dispatcher
* @param type
* @param listener
*/
public function remove(dispatcher:IEventDispatcher, type:String, listener:Function):void{
var k:Array, len:int
for(var item:* in check){
k = check[item];
len = k.length;
while(--len > -1){
if(k[len].dispatcher == dispatcher && k[len].type == type && k[len].listener == listener){
k.splice(len, 1)[0].remove();
}
}
if(k.length == 0){
check[item] = undefined;
delete check[item];
}
}
}
/**
* 移除指定监测显示对象为键的所有事件监听函数方法
* @param lifeCircleDisplay
*/
public function clear(lifeCircleDisplay:DisplayObject):void{
if(lifeCircleDisplay in check){
var k:Array = check[lifeCircleDisplay];
var len:int = k.length;
while(--len > -1){
k[len].remove();
}
check[lifeCircleDisplay] = undefined;
delete check[lifeCircleDisplay];
}
}
}
}
import flash.events.Event;
import flash.events.IEventDispatcher;
/**
* 避免大规模使用动态函数对象, 其所造成的内存消耗很大, 由此创建普通对象存储对应函数引用
* 如下使用内置的getSize获取创建对象的字节数可发现
* var s:Sprite = new Sprite();
* trace(getSize(function():void{})); //654
* trace(getSize(s.addEventListener)); //256
*/
internal class Nd{
public var listener:Function;
public var dispatcher:IEventDispatcher;
public var type:String;
public var display:DisplayObject;
public function Nd(d:IEventDispatcher, type:String, listener:Function, dis:DisplayObject):void{
this.dispatcher = d;
this.type = type;
this.listener = listener;
this.display = dis;
}
public function remove():void{
this.dispatcher.removeEventListener(this.type, this.listener);
}
}
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
/**
* 检查是否存在指定的父子级显示层级关系
* @param detectDisplay
* @param detectParent
* @return
*/
internal function checkParent(detectDisplay:DisplayObject, detectParent:DisplayObject):Boolean{
if(detectDisplay == detectParent){
return true;
}
if(detectParent is DisplayObjectContainer){
if(DisplayObjectContainer(detectParent).contains(detectDisplay)){
return true;
}
}
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment