奴隶与死囚优化法则追求的是用最少的UI实例显示更多的数据 ,占用最少的内存的一种极限优化法则,举个例子:
在 QQ中可以打开多个聊天窗口聊天,用户聊天时只会打开少数感兴趣的人的聊天窗口,当开启新聊天窗口时,如果之前有关闭的窗口,可以重用关闭的窗口。好友可 以添加或删除,删除联系人后,与联系人相关的聊天窗口和关闭的窗口一样成为闲置窗口,因此也可以被重用,当内存不大时,闲置的窗口应该优先被重用,内存过 大时,闲置的窗口可以被垃圾回收,没有闲置窗口时只能从新创建新窗口。我们需要使用最少的弹出窗口显示尽可能多的数据条目需要动态创建弹出窗口,已关闭的 窗口也要满足垃圾回收的条件,是否创建新的窗口实例取决于闲置窗口的数量,为达到这一目的,我想出(原创)一种称为“奴隶与死囚”的优化法则,其描述如 下:
奴 隶是能够工作有价值的角色,不可以屠杀,死囚是被关入监狱没有价值的角色,可以被屠杀。当奴隶抗议工作失去价值后将没收劳动工具被扔到监狱成为死囚,因为 不断有奴隶起义,监狱会发生爆满,此时为了容纳新的死囚会屠杀一批旧犯,当需要新的奴隶时为节省成本,会优先考虑从监狱中释放死囚重新成为奴隶并赋予他劳 动工具,如果监狱中没有剩余的奴隶,只有重新购买新的奴隶,招募奴隶和处决死囚取决于工作需求,这种做法虽然听起来有点血腥,但却是最节省成本的做法,我 们来看看实际工作中履行此法则角色和发生的事件 :
奴隶-打开的窗口
死囚-关闭的窗口
监狱-Dictionary
死刑执行者-垃圾回收器
劳动工具-影响到垃圾回收的引用或事件侦听
监狱爆满-内存过大
购买新的奴隶-创建新的窗口
提取死囚--使用关闭但未销毁的窗口
实现代码 如下:
WeekWindow.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="400" height="300"
showCloseButton="true" close="close()">
<mx:Script>
<![CDATA[
import flash.utils.getTimer;
import mx.core.Application;
import mx.managers.PopUpManager;
private static var limbo:Dictionary=new Dictionary(true);
public static function show(parent:DisplayObject=null, modal:Boolean=false, childList:String=null):WeekWindow
{
var w:WeekWindow;
if (parent == null)
{
parent=Application.application as Application;
}
//寻找幸存者
for(var o:Object in limbo)
{
w=o as WeekWindow;
break;
}
//找到则充军
if(w)
{
PopUpManager.addPopUp(w, parent, modal, childList);
w.title="死囚 创建时间:"+getTimer();
delete limbo[w];
}
//未找到只有从新招募
else
{
w=PopUpManager.createPopUp(parent,WeekWindow,modal,childList) as WeekWindow;
w.title="奴隶 创建时间:"+getTimer();
}
PopUpManager.centerPopUp(w);
return w;
}
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
public function close():void
{
if (isPopUp)
{
PopUpManager.removePopUp(this);
limbo[this]=1;
}
}
]]>
</mx:Script>
</mx:TitleWindow>
Test.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.modules.ModuleManager;
private var window:WeekWindow;
private function showWeekWindow():void
{
window=WeekWindow.show();
window=null;
}
]]>
</mx:Script>
<mx:Button id="bt1" label="创建" click="showWeekWindow()" />
<mx:Button id="bt2" label="垃圾回收" click="System.gc()" x="56"/>
</mx:Application>
这段代码在调试模式下运行,因为gc()方法只在调试模式下起作用,当点击创建窗口时会不断创建“奴隶”,如果关闭一部分窗口在创建,会发现优先从监狱中 取出死囚,如果进行垃圾回收则这些死囚不复存在。代码中的核心技巧是使用Dictionary创建弱引用,使用弱引用时如果对某个对象的唯一引用位于指定 的 Dictionary 对象中,则键符合垃圾回收的条件,并且在回收对象时会被从表中删除。
使用奴隶与死囚优化法则的窗口必须满足两个条件:
1.
能够被垃圾回收
2.
关闭后需要重置界面以便下次实用
为了便于垃圾回收,弹出窗口与外部的数据交互最好使用回调事件,使用窗口属性和广播事件都会给垃圾回收带来不便,如一定要广播事件,请在窗口关闭后做好清理工作。当窗口关闭后,如果窗口有最大化、最小化状态,请还原成标准状态且重置为原始大小。奴隶与死囚优化法则容易理解,难点是做好垃圾回收的工作,不仅引用会影响垃圾回收,外部绑定或效果(如SetEventHandler)也会影响垃圾回收工作,因此如果你准备制作一个便于垃圾回收的界面,在创建过程中应该时常测试新增的代码是否影响其垃圾回收。
奴隶与死囚优化法则的不仅表现在多个弹出窗口问题上,也可以大量用于游戏中。 希望我的思路对大家有所帮助。