博客公告(点击显示/隐藏)|  今日心情:转眼间又快踏入新的一年~新年新气象~
2008-08-20 23:41:27
敬告所有想在我博客刷广告的朋友先看一下这篇文章

小S吧今天你来了吗?更新速度:每周2-3篇以上!
在俺博客看到有用的东西,学习了之后,记得回访带点人气哦 ^_^ 嘿嘿!
欢迎跟俺交换友情链接啊。。留言,直接QQ等联系我都行啊
转载本博客文章请注明:来源小S吧——sunbright博客,链接地址:http://www.xiaos8.com

今年要去老婆老家过年,因此没啥机会上网了,所以在这提前祝大家新年快乐
如果你在过年期间,看到了这封帖子,并且还回帖了 [表情19]
这么意味着你2010年的运势将前程似锦,步步高升!

工作的,节节高升!
上学的,门门百分!
做生意的,财源广进!
已经赚大钱的,恭喜发财,红包拿来!
[表情06] [表情06]

今天依旧如故玩着DNF消遣,但突然一句世界频道发出来的话,把我震惊了!
uploads/201002/07_155621_screenshot0207_155225328.jpg

应该不是九城派人去DNF这样拉人的吧?但是又有什么理由能让我们相信这是个人行为呢?
九城失去魔兽,难道真的输不起吗?
我去体验过《名将三国》,当然不是冲着那Q币去的,玩了三个号每次换新号的原因都是卡在了新手任务中,无法进行下去,所以就没玩了。
过多的评价我不说了,我不是枪手也不是写软文,所以也不说太多了,只是把我看到的讲出来罢了~
在公司门口和策划部门主管合影,值得一提的我们公司与CCTV合作,举办了“希望之星”英语风采大赛
uploads/201001/29_212722_100_1203.jpg

“希望英语”唯智学园专区地址:http://wiz.cctvoe.com
我们公司产品唯智学园官方主页:http://www.wizworldonline.com

年会现场,还有很多同事没到额 - -!
uploads/201001/29_212728_100_1209.jpg

哥俩好啊~~这是我老家的兄弟,有幸现在在同一个公司,我们是从小长大的好兄弟~
uploads/201001/29_212732_100_1240.jpg

我的吃像就不敢拍了,拍个食物来勾引一下大家吧~
uploads/201001/29_212736_100_1247.jpg

我跟Rick.Goodman的合影,Rick是我们公司的副总裁兼首席产品官,当然他还有另外一个很好很强大的身份:《帝国时代》的总策划,百度百科地址:http://baike.baidu.com/view/3183300.html
uploads/201001/29_212741_100_1269.jpg

引言
在2010年1月24日在上海举办的Flash开发者交流会中,我曾经在会场上讲了Tween,URLLoader等类,会因为使用弱引用侦听而导致错误,是什么原因出错呢?下面讲的就是错误的根源,也算是对于我那天所讲,做一个全面的补充。(另外:感谢李正民同学让我了解了"引用计数"这个专业词)
首先我们来看一个Flash和一段代码:
点击上方的黑色小按钮,点一次发现效果还不错,那么你在开始有间隔的狂点这个小按钮,点的次数多了,时间长了,BUG就出现了,会发现有些动画卡住了,显示对象有时候不会运动到四周。
下面的代码就是这个Flash的源码,看过了BUG后,接下来谁能在代码中发现这个BUG是如何引发的呢?
package
{
  import fl.transitions.Tween;
  import fl.transitions.easing.Bounce;
  
  import flash.display.Bitmap;
  import flash.display.Sprite;
  import flash.events.MouseEvent;

  public class TestShow extends Sprite
  {
    [Embed (source="1.jpg")]
    private var Pic:Class;
    
    private var btn:Sprite;
    private var centerX:int;
    private var centerY:int;
    
    public function TestShow()
    {
      init();
    }
    
    //初始化
    private function init():void{
      centerX = stage.stageWidth / 2;
      centerY = stage.stageHeight / 2;
      
      btn = new Sprite;
      btn.graphics.beginFill(0,0.5);
      btn.graphics.drawRect(centerX - 10,0,20,10);
      btn.graphics.endFill();
      btn.buttonMode = true;
      stage.addChild(btn);
      
      btn.addEventListener(MouseEvent.CLICK,clickHandle);
    }
    
    //点击创建
    private function clickHandle(e:MouseEvent):void{
      var width:int = stage.stageWidth;
      var height:int = stage.stageHeight;
      for(var i:int = 0; i <= 8; i ++){
        var x:int = centerX,y:int = centerY;
        if(i == 4) continue;
        if(i % 3 == 0) x = 0;
        else if(i % 3 == 2) x = width;
        if(i < 3) y = 0;
        else if(i > 5) y = height;
        create(x,y);
      }
    }
    
    //创建一个
    private function create(x:int,y:int):void{
      var spr:Sprite = new Sprite;
      var pic:Bitmap = new Pic;
      pic.x = - pic.width / 2;
      pic.y = - pic.height / 2;
      spr.addChild(pic);
      spr.x = centerX;
      spr.y = centerY;
      setAnimation(spr,x,y);
      addChild(spr);
    }
    
    //创建动画
    private function setAnimation(spr:Sprite,x:int,y:int):void{
      var tweenX:Tween = new Tween(spr,"x",Bounce.easeOut,spr.x,x,50);
      var tweenY:Tween = new Tween(spr,"y",Bounce.easeOut,spr.y,y,50);
    }
  }
}

看到这儿,聪明的开发者不知道你有没有思考过呢?但下面来看看我分析的原因:
首先我们回顾一些知识点:

Flash的自动内存回收分为两个方式,1是是否引用计数为0,2是是否存在Stage中。
我们现在来关心下第一个方式:
当一次强引用,该对象的引用计数加1;
当一次弱引用,该对象的引用计数不加;
当强引用侦听事件,引用计数加1,弱引用不加;
问题:那么什么情况下是强引用,什么是弱引用呢?
当然这里有很多种情况,我这列举两条:
1、事件侦听时,addEventListener的第5个参数,为true表示弱引用侦听,为false反之(默认是false,即强引用侦听);
2、在Function中的变量引用,虽然不能说他就是弱引用,但Function执行完毕后,该引用计数其实并没有加1
比如以下Code,就算调用了func,Sprite实例对象的引用计数还是只有1
private var spr:Sprite = new Sprite;
private function func():void{
  var a:Sprite = spr;
}
我们现在来看这段代码:
//创建动画
private function setAnimation(spr:Sprite,x:int,y:int):void{
  var tweenX:Tween = new Tween(spr,"x",Bounce.easeOut,spr.x,x,50);
  var tweenY:Tween = new Tween(spr,"y",Bounce.easeOut,spr.y,y,50);
}
从这段代码不难理解,两个new Tween分别创建了两个Tween实例,并分别被tweenX和tweenY引用,但tweenX,tweenY它是局部引用,当这个Function执行完后,创建的两个Tween实例引用计数就是0,那么这时候如果启动了自动内存回收,理论上Tween类的两个实例都会被回收掉,结果也正是如此!所以上面问题出现了!
怎么解决呢?
首先,一个好好的动画在这儿它为什么会被自动回收掉呢?理论上动画的过程是不会被回收的!
我们来看看ADOBE官方Tween类中的一段代码:
protected function startEnterFrame():void
{
  if (isNaN(this._fps))
  {
    // original frame rate dependent way
    _mc.addEventListener(Event.ENTER_FRAME, this.onEnterFrame, false, 0, true);
  }
  else
  {
    // custom frame rate
    var milliseconds:Number = 1000 / this._fps;
    this._timer.delay = milliseconds;
  this._timer.addEventListener(TimerEvent.TIMER, this.timerHandler, false, 0, true);
  this._timer.start();
  }
  this.isPlaying = true;
}
大家可以发现,addEventListener的第5个参数是使用的弱引用侦听,这也表示如果Tween类在外部没有引用计数,而内部也没引用计数,OK,内存回收时,它自然被干掉了!
那么如何解决呢?
1、将这个地方的侦听改成强引用侦听,这个问题这样的确解决了,但是Tween引用计数加1了,因此随后你也要记得将它移除,比如加个clear的方法,来移除事件侦听。否则会内存泄露!
2、将Tween实例在类中全局引用,比如push到某个类对象数组中,但同样的问题记得用完要删除!
说了这么多,总感觉这个知识点还没说的很完整,如果谁没看懂,或者有问题问的,希望能跟帖询问,我会一一解答的!另外URLLoader等类也是存在同样的问题,如果使用弱引用侦听,而没有保存到类全局变量,如果在加载的过程中,突然碰到内存自动回收,那么这个对象也就不复存在,并且会报错,说数据不完整之类的
最后总结:
1、关于内存管理:一定是创建了就记得销毁,一定是侦听了就记得移除!不要太依靠弱引用来帮你做内存管理!
2、关于写代码习惯:有创建,就要有销毁!有addEventListener,就要有removeEventListener!
3、强弱引用是个好东西,但一定要弄清楚它的工作原理!当然任何知识点都要了解透彻!

关于这个文章,大家也可以到天地会论坛中进行讨论:http://flash.9ria.com/thread-44077-1-1.html

参加这次活动,又认识了许多新朋友,这次讲的东西都很好。
前几场的同僚讲的,比如从其他语言的角度来剖析Flash的对象;还有ADOBE在内存自动回收是如何去工作;等等,讲的非常好。
虽然以前是了解这些的,但现在感觉更深层次了解了这些内部的机制。
感谢主办方给我们带来这么好的一次聚会~
因为今天我在会场无心插柳讲出了我博客地址,那么如果谁愿意跟我交换友情连接的可以跟我说,咱们可以多交流交流~毕竟Flash未来良好的发展趋势,还是得靠我们一步步共同去挖掘。
图片名称:会场现场
uploads/201001/24_212957_100_1173.jpg

因为我公司是全封闭式开发,所有1年多来已经习惯不开IM软件(当然除了QQ,也包括MSN等主流通讯软件),所以今天在会场上有人问及我QQ还有MSN什么的,很不好意思我是真的很久没上过了,不过大家想找我可以博客留言,如果是有问题在博客留言,我承诺一定会在最短时间解答你的问题,当然我也不是万能的,涉及到框架问题我帮不了你,我不是很喜欢用框架,虽然我会去研究ASWing,PV3D等主流框架的底层结构,但从来没用过,正如今天会场上有位帅哥讲的一样,简单才是最好的。
另外大家也可以发电子邮件找我:sunkill@163.com(不是很频繁看邮箱,如果回信速度慢了,请多见谅)
当然硬说没QQ,大家也不会相信,我QQ是36806312,不过真的很久没上了,不过最近可能会上一下,当然是因为这次会场的缘故拉