博客公告(点击显示/隐藏)| 今日心情:神学
2010-07-30 21:09:43
小S吧今天你来了吗?更新速度:每周2-3篇以上!在俺博客看到有用的东西,学习了之后,记得回访带点人气哦 ^_^ 嘿嘿!
欢迎跟俺交换友情链接啊。。留言,直接QQ等联系我都行啊
转载本博客文章请注明:来源小S吧——sunbright博客,链接地址:http://www.xiaos8.com
2010
1-29
在公司门口和策划部门主管合影,值得一提的我们公司与CCTV合作,举办了“希望之星”英语风采大赛
“希望英语”唯智学园专区地址:http://wiz.cctvoe.com
我们公司产品唯智学园官方主页:http://www.wizworldonline.com年会现场,还有很多同事没到额 - -!
哥俩好啊~~这是我老家的兄弟,有幸现在在同一个公司,我们是从小长大的好兄弟~
我的吃像就不敢拍了,拍个食物来勾引一下大家吧~
我跟Rick.Goodman的合影,Rick是我们公司的副总裁兼首席产品官,当然他还有另外一个很好很强大的身份:《帝国时代》的总策划,百度百科地址:http://baike.baidu.com/view/3183300.html
![]() |
“希望英语”唯智学园专区地址:http://wiz.cctvoe.com
我们公司产品唯智学园官方主页:http://www.wizworldonline.com年会现场,还有很多同事没到额 - -!
![]() |
![]() |
![]() |
![]() |
2010
1-26
引言
在2010年1月24日在上海举办的Flash开发者交流会中,我曾经在会场上讲了Tween,URLLoader等类,会因为使用弱引用侦听而导致错误,是什么原因出错呢?下面讲的就是错误的根源,也算是对于我那天所讲,做一个全面的补充。(另外:感谢李正民同学让我了解了"引用计数"这个专业词)
点击上方的黑色小按钮,点一次发现效果还不错,那么你在开始有间隔的狂点这个小按钮,点的次数多了,时间长了,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);
}
}
}
看到这儿,聪明的开发者不知道你有没有思考过呢?但下面来看看我分析的原因:{
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;
当一次弱引用,该对象的引用计数不加;
当强引用侦听事件,引用计数加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 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类的两个实例都会被回收掉,结果也正是如此!所以上面问题出现了!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);
}
怎么解决呢?
首先,一个好好的动画在这儿它为什么会被自动回收掉呢?理论上动画的过程是不会被回收的!
我们来看看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,内存回收时,它自然被干掉了!{
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;
}
那么如何解决呢?
1、将这个地方的侦听改成强引用侦听,这个问题这样的确解决了,但是Tween引用计数加1了,因此随后你也要记得将它移除,比如加个clear的方法,来移除事件侦听。否则会内存泄露!
2、将Tween实例在类中全局引用,比如push到某个类对象数组中,但同样的问题记得用完要删除!
说了这么多,总感觉这个知识点还没说的很完整,如果谁没看懂,或者有问题问的,希望能跟帖询问,我会一一解答的!另外URLLoader等类也是存在同样的问题,如果使用弱引用侦听,而没有保存到类全局变量,如果在加载的过程中,突然碰到内存自动回收,那么这个对象也就不复存在,并且会报错,说数据不完整之类的
最后总结:
1、关于内存管理:一定是创建了就记得销毁,一定是侦听了就记得移除!不要太依靠弱引用来帮你做内存管理!
2、关于写代码习惯:有创建,就要有销毁!有addEventListener,就要有removeEventListener!
3、强弱引用是个好东西,但一定要弄清楚它的工作原理!当然任何知识点都要了解透彻!关于这个文章,大家也可以到天地会论坛中进行讨论:http://flash.9ria.com/thread-44077-1-1.html
2010
1-24
参加这次活动,又认识了许多新朋友,这次讲的东西都很好。
前几场的同僚讲的,比如从其他语言的角度来剖析Flash的对象;还有ADOBE在内存自动回收是如何去工作;等等,讲的非常好。
虽然以前是了解这些的,但现在感觉更深层次了解了这些内部的机制。
感谢主办方给我们带来这么好的一次聚会~
因为今天我在会场无心插柳讲出了我博客地址,那么如果谁愿意跟我交换友情连接的可以跟我说,咱们可以多交流交流~毕竟Flash未来良好的发展趋势,还是得靠我们一步步共同去挖掘。
因为我公司是全封闭式开发,所有1年多来已经习惯不开IM软件(当然除了QQ,也包括MSN等主流通讯软件),所以今天在会场上有人问及我QQ还有MSN什么的,很不好意思我是真的很久没上过了,不过大家想找我可以博客留言,如果是有问题在博客留言,我承诺一定会在最短时间解答你的问题,当然我也不是万能的,涉及到框架问题我帮不了你,我不是很喜欢用框架,虽然我会去研究ASWing,PV3D等主流框架的底层结构,但从来没用过,正如今天会场上有位帅哥讲的一样,简单才是最好的。
另外大家也可以发电子邮件找我:sunkill@163.com(不是很频繁看邮箱,如果回信速度慢了,请多见谅)
当然硬说没QQ,大家也不会相信,我QQ是36806312,不过真的很久没上了,不过最近可能会上一下,当然是因为这次会场的缘故拉
前几场的同僚讲的,比如从其他语言的角度来剖析Flash的对象;还有ADOBE在内存自动回收是如何去工作;等等,讲的非常好。
虽然以前是了解这些的,但现在感觉更深层次了解了这些内部的机制。
感谢主办方给我们带来这么好的一次聚会~
因为今天我在会场无心插柳讲出了我博客地址,那么如果谁愿意跟我交换友情连接的可以跟我说,咱们可以多交流交流~毕竟Flash未来良好的发展趋势,还是得靠我们一步步共同去挖掘。
图片名称:会场现场 ![]() |
因为我公司是全封闭式开发,所有1年多来已经习惯不开IM软件(当然除了QQ,也包括MSN等主流通讯软件),所以今天在会场上有人问及我QQ还有MSN什么的,很不好意思我是真的很久没上过了,不过大家想找我可以博客留言,如果是有问题在博客留言,我承诺一定会在最短时间解答你的问题,当然我也不是万能的,涉及到框架问题我帮不了你,我不是很喜欢用框架,虽然我会去研究ASWing,PV3D等主流框架的底层结构,但从来没用过,正如今天会场上有位帅哥讲的一样,简单才是最好的。
另外大家也可以发电子邮件找我:sunkill@163.com(不是很频繁看邮箱,如果回信速度慢了,请多见谅)
当然硬说没QQ,大家也不会相信,我QQ是36806312,不过真的很久没上了,不过最近可能会上一下,当然是因为这次会场的缘故拉
2010
1-14
很久没写AS3的原创技术文章了,今天来一个总结性的文章。1、TypeError: Error #1006: value 不是函数。
这是在运行时的报错,我们来看看是一段什么样的代码导致他报错的
大家先找找这段代码错在哪,为什么导致这个错误,然后在看看后面说的错误原因
我们都知道AS3的代码,如果没有";"的情况下也是可以编译、可以运行的。不过恰恰上述代码在e.updateAfterEvent()后因为没有";",导致他运行错误。因为这段代码在运行时,它是被当成了这样在运行
总结1:大家明白了吗?从上面这个例子可以看出,养成加";"号的习惯还是非常重要的。2、TypeError: Error #1034: 强制转换类型失败:无法将 flash.events::Event 转换为 MyEvent。
同样这也是一个运行错误,我们来看看是一段什么样的代码导致他报错的
大家也先找找他的错在哪首先先看一下这个MyEvent类
很多新手在看高手的代码,都会看到自定义事件中都会重构clone这个方法,但是自己尝试后发现,不重构clone也不会出现什么问题,以至于有些人在写项目赶时间时,也不太喜欢100%模仿高手的写法,就会把重构clone这个看似很小,其实隐藏了秘密的东西给忽略掉。
在殿堂之路中有句原话:而上面的代码中就是在将MyEvent事件重复发送,好理解的说就是转发MyEvent事件,如果没有重构MyEvent事件,那么EventDispatcher在重复发送时,调用的clone是Event的clone方法,那么clone出来的事件自然就是Event类,而不是MyEvent,所以你在侦听时使用e:MyEvent类型接收时,自然就会报错无法将Event类转换成MyEvent类。
总结2:看书要仔细,看高手的代码一定要学习透彻,而不是拿来主义,或者是模仿主义!
引言
在写AS3代码的过程中,有些编译错误,或者运行错误,是很难检查。这儿我总结了一些曾经碰到过的问题。
这是在运行时的报错,我们来看看是一段什么样的代码导致他报错的
大家先找找这段代码错在哪,为什么导致这个错误,然后在看看后面说的错误原因
private function clickHandle(e:MouseEvent):void{
if(e.currentTarget is Sprite){
e.updateAfterEvent()
(e.currentTarget as Sprite).visible = false;
}
}
如果你是传统程序员,这个错误一般情况来说,你都不会犯的;如果你是AS2到AS3的,或者说你以前写asp等网页程序的,这个问题的引发几率就相对比较高了。if(e.currentTarget is Sprite){
e.updateAfterEvent()
(e.currentTarget as Sprite).visible = false;
}
}
我们都知道AS3的代码,如果没有";"的情况下也是可以编译、可以运行的。不过恰恰上述代码在e.updateAfterEvent()后因为没有";",导致他运行错误。因为这段代码在运行时,它是被当成了这样在运行
e.updateAfterEvent()(e.currentTarget as Sprite).visible = false;
updateAfterEvent返回的是void类型,那么把他当成函数来调用,自然会报错 value 不是函数。总结1:大家明白了吗?从上面这个例子可以看出,养成加";"号的习惯还是非常重要的。2、TypeError: Error #1034: 强制转换类型失败:无法将 flash.events::Event 转换为 MyEvent。
同样这也是一个运行错误,我们来看看是一段什么样的代码导致他报错的
大家也先找找他的错在哪首先先看一下这个MyEvent类
package
{
import flash.events.Event; public class MyEvent extends Event
{
public static const MY:String = "my";
public function MyEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}
然后侦听这个事件,在得到它后转发到spr对象中{
import flash.events.Event; public class MyEvent extends Event
{
public static const MY:String = "my";
public function MyEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}
addEventListener(MyEvent.MY,myHandle);
private function myHandle(e:MyEvent):void{
spr.dispatchEvent(e);
}
再就是,spr对象中侦听了这个事件private function myHandle(e:MyEvent):void{
spr.dispatchEvent(e);
}
spr.addEventListener(MyEvent.MY,myHandle);
private function myHandle(e:MyEvent):void{
trace(e);
}
最后在这个侦听的地方就报错了。在殿堂之路中,继承Event自定义事件举例中讲过这种问题的解决办法,但没有讲的很详细private function myHandle(e:MyEvent):void{
trace(e);
}
很多新手在看高手的代码,都会看到自定义事件中都会重构clone这个方法,但是自己尝试后发现,不重构clone也不会出现什么问题,以至于有些人在写项目赶时间时,也不太喜欢100%模仿高手的写法,就会把重构clone这个看似很小,其实隐藏了秘密的东西给忽略掉。
在殿堂之路中有句原话:
以下摘抄《殿堂之路》第300页原话
其中clone()方法最为重要,使用clone()方法可以返回当前事件对象的一个拷贝。这个clone()方法一般不需要我们手工调用,当我们将一个事件对象重复发送时,EventDispatcher类会自动调用clone()方法,产生这个事件的拷贝。
总结2:看书要仔细,看高手的代码一定要学习透彻,而不是拿来主义,或者是模仿主义!
2010
1-12
SELECT 指令让我们能够读取表格中一个或数个栏位的所有资料。这将把所有的资料都抓出,无论资料值有无重复。在资料处理中,我们会经常碰到需要找出表格内的不同资料值的情况。换句话说,我们需要知道这个表格/栏位内有哪些不同的值,而每个值出现的次数并不重要。这要如何达成呢?在 SQL 中,这是很容易做到的。我们只要在 SELECT 后加上一个 DISTINCT 就可以了。
Store_Information表格
我们就打入
SELECT DISTINCT store_name FROM Store_Information
结果:
store_name
Los Angeles
San Diego
Boston
DISTINCT 的语法如下:
SELECT DISTINCT "栏位名" FROM "表格名"
Store_Information表格
| store_name | sales | date |
| Los Angeles | $1500 | jan-05-1999 |
| San Diego | $250 | jan-07-1999 |
| Los Angeles | $300 | jan-08-1999 |
| Boston | $700 | jan-08-1999 |
SELECT DISTINCT store_name FROM Store_Information
结果:
store_name
Los Angeles
San Diego
Boston










- 查看svn更新内容以及最新状态(实时更新)
- 查看框架API文档(09.6.15更新)
- 查看框架代码(09.4.20更新)
框架暂停开发,且没有完全竣工,目前只能使用air包和library包!