今天,在做一个的项目。遇到Vector的深复制,发现复制竟然不成功。(Vector里边存储的复杂数据MovieClip)。今天先记录这里,下次再研究。在想办法解决ing。 下边先进行些简单的测试。然后,用网上的方法测试。先看code:
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.utils.ByteArray; public class ArrayCopy extends Sprite { public function ArrayCopy() { var a:Array = [1 , 2 , 3]; var b:Array = a; a.splice(0); trace("1_1 a:"+ a , "b:" + b); //输出:1_1 a: b: b = []; a = [1 , 2 , 3]; b = a; b.splice(0); trace("1_2 a:"+ a , "b:" + b); //输出: 1_2 a: b: b = []; a = [1 , 2 , 3]; b = a; a[0] = 2; trace("1_3 a:"+ a , "b:" + b); //输出:1_3 a:2,2,3 b:2,2,3 /* 通过以上的测试,能够知道,数组间的直接赋值,改变了任意一个数组里边的元素,
另外一个也会改变。无论数据是基元数据类型还是复杂数据类型
*/ b = []; a = [1,2,3]; b = a.slice(); a.splice(0); trace("2 a:"+ a , "b:" + b); //输出:2 a: b:1,2,3 b = []; a = [1,2,3]; b = a.concat(); a.splice(0); trace("3 a:"+ a , "b:" + b); //输出:3 a: b:1,2,3 b = []; a = [1,2,3]; for each(var i:int in a) { b.push(i); } a.splice(0); trace("4 a:"+ a , "b:" + b); //输出:4 a: b:1,2,3 /* 通过以上的测试,能够知道,基元数据类型的浅复制,改变了一个数组,另外一个数组不会改变
*/ b = []; a = [ 1 , "vini" , true]; b = a.slice(); a[0] = "gg" ; a[1] = 2; a[2] = false; trace("5 a:"+ a , "b:" + b); //输出:5 a:gg,2,false b:1,vini,true b= []; a = [1 , [1 , 2],3]; b = a.slice(); a[1] = [100,200]; trace("6 a:"+ a , "b:" + b); //输出:6 a:1,100,200,3 b:1,1,2,3 b= []; a = [1 , {a:1,b:2},3]; b = a.slice(); a[1].a = 100; a[1].b = 200; trace("7 a:"+ a[1].a , "b:" + b[1].a); //输出:7 a:100 b:100 /* 通过以上的测试,能够知道,基元数据类型的浅复制,改变了一个数组,
另外一个数组不会改变(如果是Array其内层值也是基元数据类型),
复杂数据类型则会改变
*/ b= []; a = [1 , {a:1,b:2},3]; var byteArray:ByteArray = new ByteArray(); byteArray.writeObject(a); byteArray.position = 0; b = byteArray.readObject(); a[1].a = 100; a[1].b = 200; trace("8 a:"+ a[1].a , "b:" + b[1].a); //输出 8 a:100 b:1 b= []; var mc:MovieClip = new MovieClip(); mc.id = 5; a = [1 , mc , 3]; byteArray = new ByteArray(); byteArray.writeObject(a); byteArray.position = 0; b = byteArray.readObject(); (a[1] as MovieClip).id = 500; trace("9 a:"+ a[1] , "b:" + b[1]); //输出 9 a:[object MovieClip] b:undefined /* 通过以上的测试,能够知道,数据的深复制,像MovieClip这样的复杂数据,
不能深复制成功,object里边如果是基元数据,可以深复制成功
*/
var roll:Roll = new Roll(); roll.id = 5; b = []; a = [1 , roll , 3]; byteArray = new ByteArray(); byteArray.writeObject(a); byteArray.position = 0; b = byteArray.readObject(); roll.id = 500; trace("10 a:"+ a[1].id , "b:" + b[1].id , "b:" + b[1].mc); //输出 10 a:500 b:5 b:undefined /* 通过以上的测试,能够知道,普通的类可以深复制,像MovieClip这样的复杂数据,
不能深复制成功。
*/ } } }
package com.vini123 { import flash.display.MovieClip; public class Roll { private var _id:int = 0; private var _mc:MovieClip; public function Roll() { _mc = new MovieClip(); } public function get id():int { return _id; } public function set id(value:int):void { _id = value; _mc.id = _id; } public function get mc():MovieClip { return _mc; } } }
然后,如果Roll里边有Point,自定义类等呢。于是,找到了registerClassAlias。哎,平时没遇到,也没一个一个去阅读官方API,很多API都很陌生。像这些顶级API以前竟然没用过。
registerClassAlias(aliasName:String, classObject:Class):void
当以 Action Message Format (AMF) 对一个对象进行编码时,保留该对象的类(类型)。
语言版本: ActionScript 3.0
运行时版本: AIR 1.0, Flash Player 9, Flash Lite 4
当以 Action Message Format (AMF) 对一个对象进行编码时,保留该对象的类(类型)。将对象编码为 AMF 时,该函数将保存该对象的类的别名,以便在解码对象时可以恢复该类。如果编码上下文没有为对象的类注册别名,该对象将被编码为一个匿名对象。同样,如果解码上下文注册了不同的别名,将为解码后的数据创建一个匿名对象。
LocalConnection、ByteArray、SharedObject、NetConnection 及 NetStream 均为将对象编码为 AMF 的类的示例。
编码和解码上下文不必对别名使用相同的类。它们可以主动地改变类,条件是目标类包含源类序列化的所有成员。
参数
aliasName:String — 要使用的别名。
classObject:Class — 与给定别名相关联的类。
registerClassAlias在利用AMF3进行序列话网络通讯中,是非常有用的。需要把客户端的对象直接传送到服务器得时候,保留该对象的类(类型)。 这样的话,就可以传送自定义对象或者系统自带对象。
readObject方法对构造器有参数的类,是会出错的,会弹出参数数量不匹配这个错误。因为还原对象进行反射的时候,是默认没有参数的给构造器的。这也是有些人 讨论Sprite等对象不能进行深度拷贝的原因。所以在使用AMF3进行序列话的时候要注意这个了,还有一个就是,如果那个类包含了多个类,也就是个复合类,那么里面的那个复合类,也必须进行registerClassAlias
于是,修改了代码,参考网上的。对深复制进行试验。
1.显示对象是可以深复制的。如果这样,将颠覆以前所说的显示对象不能深复制的问题。先贴出代码吧。
文档类:Main.as
package com.vini123 { import com.vini123.source.Roll; import com.vini123.utils.ObjectUtils; import flash.display.Sprite; public class Main extends Sprite { public function Main() { var roll:Roll = new Roll(); var otherRoll:Roll roll.id = 200; roll.point.y = 1; otherRoll = ObjectUtils.clone(roll); roll.id = 100; roll.point.x = 100; roll.point.y = 100; roll.sky.height = 100; trace("roll:" , roll.id , roll.point, roll.mc.id , roll.sky.height); trace("otherRoll:" , otherRoll.id , otherRoll.point , otherRoll.mc.id , otherRoll.sky.height); addChild(otherRoll.mc); otherRoll.mc.x = stage.stageWidth * 0.5 -40; otherRoll.mc.y = stage.stageHeight * 0.5; addChild(roll.mc); roll.mc.x = otherRoll.mc.x + 80; roll.mc.y = otherRoll.mc.y; } } }
Roll.as 类:
package com.vini123.source { import flash.display.MovieClip; import flash.geom.Point; public class Roll { private var _id:int = 0; private var _mc:MovieClip; private var _point:Point; private var _sky:Sky; public function Roll() { _mc = new MovieClip(); _point = new Point(); _sky = new Sky(); doGraphics(); } public function get id():int { return _id; } public function set id(value:int):void { _id = value; _mc.id = _id; _point.x = _id; _point.y = _id; sky.height = _id; } public function get mc():MovieClip { return _mc; } public function get point():Point { return _point; } public function get sky():Sky { return _sky; } private function doGraphics():void { _mc.graphics.beginFill(0x0ff,0.36); mc.graphics.lineStyle(1,0xff0,0.6); _mc.graphics.drawCircle(0,0,180); _mc.graphics.endFill(); } } }
Sky.as 类:
package com.vini123.source { public class Sky { private var _height:int = 0; public function Sky() { } public function get height():int { return _height; } public function set height(value:int):void { _height = value; } } }
工具转化类,ObjectUtils.as 类:
package com.vini123.utils { import flash.net.registerClassAlias; import flash.utils.ByteArray; import flash.utils.describeType; import flash.utils.getDefinitionByName; import flash.utils.getQualifiedClassName; public class ObjectUtils { private static var _aliasList:Vector.<String> = new Vector.<String>(); public function ObjectUtils() { } /** * * @param source 源 * @param deep 是否深复制 * @return * */ public static function clone(source:* , deep:Boolean = true):* { if(!source) { return ; } if(deep) { var qualifiedClassName:String = getQualifiedClassName(source); if(_aliasList.indexOf(qualifiedClassName)) { var packageName:String = qualifiedClassName.replace("::","."); //得到source的类的定义 var classType:Class = getDefinitionByName(qualifiedClassName) as Class; //注册此别名和类 if(classType) { registerClassAlias(packageName , classType); _aliasList.push(qualifiedClassName); } //注册内部的属性 registerVariables(source); } } var byteArray:ByteArray = new ByteArray(); byteArray.writeObject(source); byteArray.position = 0 ; trace(_aliasList); return byteArray.readObject(); } /** * * @param source * 注册某个类的公共属性(如果是复合类)所属的类的别名. * */ private static function registerVariables(source:*):void { var xml:XML = describeType(source); var variable:XML; var variableType:String; var variablePackageName:String; var variableClassType:Class; var variableXml:XMLList; //判断source的类型,是对象或是Class if(source is Class) { variableXml = xml.factory.variable; //获取类中的相关的属性 } else { variableXml = xml.accessor; //获取对象中相关的属性 } for each(variable in variableXml) { variableType = variable.@type; //属性的类型,可能是Number,类等。 if(variableType.indexOf("::")!=-1) { //如果没有该类没有进行registerClassAlia if(_aliasList.indexOf(variableType) == -1) { variablePackageName = variableType.replace("::","."); //得到类的别名 variableClassType = getDefinitionByName(variableType) as Class; //得到类名 if(variableClassType); { registerClassAlias(variablePackageName,variableClassType); registerVariables(variableClassType); _aliasList.push(variableType); } } } } } } }
运行后的结果:
trace的情况:
com.vini123.source::Roll,flash.geom::Point,com.vini123.source::Sky,flash.display::MovieClip
roll: 100 (x=100, y=100) 100 100
otherRoll: 200 (x=200, y=200) 200 200
第一行,是保留对象的类名。
第二行和第三行的结果,显示深复制的效果是有的。并且,在main中对Roll中的Point进行赋值时,深复制不到。其实,Sky类的hight,MovieClip的id同样不行。还冒明白。
最后的两个addChild.在舞台上,显示了两个圆,两个之间的x距离是80像素。证明显示对象的深复制是有效果的。因为该显示对象是在Roll中创建的。。。
到了现在,对象的深浅复制貌似意义不大。如果仅仅是复制的话。这些总结,只是个人的测试。欢迎朋友去完善和拓展吧。
不死心,为了进一步测试。这次用Flash cs6 创建一个影片剪辑,里边放了一张兔子的照片为背景。并有一个动态文本,infoTxt。将该影片剪辑连接到Skin类,Skin继承MovieClip
先创建一个Vector数组,初始化的时候,创建两个Skin,添加到显示列表,并填充到这个数组中。当点击舞台的时候,将这个数组中的Skin”深复制“到一个新的Vector中,释放旧的Skin,移出显示列表。2秒后,再将新数组中的Skin添加到显示列表。
(想法是美好的,当往新数组中深复制Skin的时候,Skin已经是undefined了。这个时候添加显然要报错。)
如是,证明,显示对象不能深复制。如果这样,和之前的结论不是互相矛盾么。
先看代码:
package com.vini123.view { import flash.display.MovieClip; import flash.net.registerClassAlias; import flash.text.TextField; public class Skin extends MovieClip { public var infoTxt:TextField; public function Skin() { registerClassAlias("infoTxt",TextField); } public function set info(value:String):void { infoTxt.text = value; } public function Dispose():void { infoTxt.text = ""; if(this.parent) { this.parent.removeChild(this); } } } }
文档类:
package com.vini123 { import com.vini123.utils.ObjectUtils; import com.vini123.view.Skin; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.MouseEvent; import flash.utils.setTimeout; [SWF(width = "1280" , height = "720" , frameRate="30")] public class Main extends Sprite { private var _originalSkinList:Vector.<Skin> = new Vector.<Skin>(); private var _newSkinList:Vector.<Skin> = new Vector.<Skin>(); private var _hasClick:Boolean = false; private var _gap:int = 50; public function Main() { stage.align = StageAlign.TOP_LEFT; Init(); } private function Init():void { for(var i:int = 0 ; i< 2 ; i++) { var skin:Skin = new Skin(); skin.info = "这个是第" + (i + 1) + "只兔子!"; addChild(skin); skin.x = (stage.stageWidth - skin.width *2 -_gap)/2 + i * (skin.width + 50); skin.y = stage.stageHeight * 0.5 - skin.height * 0.5 ; _originalSkinList.push(skin); } stage.addEventListener(MouseEvent.MOUSE_DOWN , mouseDownHandler); } private function mouseDownHandler(e:MouseEvent):void { if(!_hasClick) { _hasClick = true; for(var i:int =0 ; i< _originalSkinList.length ; i++) { trace(ObjectUtils.clone(_originalSkinList[i])); _newSkinList.push(ObjectUtils.clone(_originalSkinList[i])); } for(i = (_originalSkinList.length -1) ; i>= 0 ; i--) { _originalSkinList[i].Dispose(); _originalSkinList.splice(i,1); } setTimeout( addAgain , 2000); } } private function addAgain():void { for(var i:int = 0 ; i< _newSkinList.length ; i++) { trace(_newSkinList[i]); // addChild(_newSkinList[i]); // _newSkinList[i].x = (stage.stageWidth - _newSkinList[i].width *2 -_gap)/2 + i * (_newSkinList[i].width + 50); // _newSkinList[i].y = stage.stageHeight * 0.5 - _newSkinList[i].height * 0.5 ; } } } }