www.adobeshow.com
存档 Archives : 十月, 2009

RTMFP协议 什么是Stratus?

<Category: Stratus> 发表评论

RTMFP — RTMFP是Adobe公司开发的一套新的通信协议,该协议可以让使用Adobe Flash Player的终端用户之间进行直接通信, RTMFP基于UDP而Flash Media Service支持的RTMP是基于TCP的。

Stratus — Adobe Stratus service beta 是支持RTMFP 的服务器。它是一个中转式的服务,它的作用是建立flash player之间的通讯。即使它们位于NATs的后面。与FMS不同,Stratus不支持媒体转播,共享对象,脚本等等,你只能开发客户端之间直接联系的应用程序。

本文来自: RTMFP协议 什么是Stratus?

地理(投影)坐标与屏幕坐标的转换!

<Category: 算法公式> 发表评论

地理坐标定义规则:X轴(代表经度)向右递增,Y轴(纬度)向上递增,就好比小学学过的平面坐标(貌似又忘了,要重读小学了)吧?向左,向下的规则,这个不用我再阐述了吧

    屏幕坐标定义规则:X轴向右递增,Y轴向下递增..
    可以看出,地理坐标和屏幕坐标的区别仅仅只是在于Y轴递增方向是相反的…(这就是不同).
    好了,现在我们开始转换他们吧.  这里强调一点的就是为了保证精度,地理坐标的度*3600换算成秒,所有的取值用double来计算,最后的结果再转换成int
    1.已知道屏幕的高(y)和宽(h),地理坐标区域的范围(maxLon,minLon,maxLat,minLat)..这里我们知道了这些已知的参数…
    2.我们可以算出每像素所代表的经度和纬度(有人称这个为比例因子):
        公式:scaleX = h/((maxLon-minLon)*3600)  ———-X轴上每像素代表的经度秒数;
        公式:scaleY = y/((maxLat-minLat)*3600)  ———–Y轴上每像素代表的纬度秒数;
        这两个比例因子就是两个坐标系之间的关系..
    3.很简单的一步了,那就是算出该地理坐标区域中的任何一点(lon,lat)在屏幕上的坐标了,怎么算?下面来讲:
       公式:screenX = lon*3600/scaleX;  ———屏幕坐标X轴坐标
       公式:screenY = lat*3600/scaleY; ———-屏幕坐标Y轴坐标,        怎么样?很简单吧?这里我们就算出地理坐标上任何一点转到屏幕上的坐标是多少了……
        还有最后一步,那就是我们要把该地理区域占满占个屏幕该怎么办呢?
   4. 接着我们需要该地理区域占满占个屏幕该怎么办呢
        公式:minX = minLon*3600/scaleX;    区域左边置最左端
        公式:minY = minLat*3600/scaleY;     区域上面置最上端
   5. 当地地理范围区域占满整个屏幕时,我们需要用到第三步计算出来的 screenX和screenY两个参数
,该区域中的任何一点的公式如下:   
       公式:X = screenX – minX = (lon – minLon)*3600/scaleX;     
       由于纬度的方向和屏幕Y轴是相反的, 
       公式:screenMaxLat = (maxLat – minLat)*3600/scaleY;
       公式:screenLat = (lat – minLat)*3600/scaleY;
       公式:Y = screenMaxLat – screenLat = (maxLat – lat)*3600/scaleY;     至于为什么是这个公式,我想大家仔细想想就明白了..
  6.总结:
        经纬度转屏幕坐标的最终公式如下:
        公式: X = (lon – minLon)*3600/scaleX;  
        公式: Y =  (maxLat – lat)*3600/scaleY;
  接着我们由上面的公式可以推出屏幕坐标转经纬度坐标公式如下:
  公式:lon = X * scaleX/3600 + minLon;
        公式:lat = maxLat – y* scaleY/3600;

本文来自: 地理(投影)坐标与屏幕坐标的转换!

Flash-一些常用物理公式和AS3的结合应用

<Category: ActionScript 3.0, Flash, Flex, Flex3, Flex4, 算法公式> 发表评论

来自《Foundation Actionscript 3.0 Animation: Making Things Move!》的物理公式:
向鼠标(或者任何一个点)旋转:

// 用要旋转到的 x, y 坐标替换 mouseX, mouseY
dx = mouseX - sprite.x;
dy = mouseY - sprite.y;
sprite.rotation = Math.atan2(dy, dx) * 180 / Math.PI;

创建波形:

// 将 x, y 或其它属性赋值给 Sprite 影片或影片剪辑,
// 作为绘图坐标,等等。
public function onEnterFrame(event:Event){
value = center + Math.sin(angle) * range;
angle += speed;
}

创建圆形:

// 将 x, y 或其它属性赋值给 Sprite 影片或影片剪辑,

// 作为绘图坐标,等等。
public function onEnterFrame(event:Event){
xposition = centerX + Math.cos(angle) * radius;
yposition = centerY + Math.sin(angle) * radius;
angle += speed;
}

创建椭圆:

// 将 x, y 或其它属性赋值给 Sprite 影片或影片剪辑,
// 作为绘图坐标,等等。
public function onEnterFrame(event:Event){
xposition = centerX + Math.cos(angle) * radiusX;
yposition = centerY + Math.sin(angle) * radiusY;
angle += speed;
}

获得两点间的距离:

// x1, y1 和 x2, y2 是两个点
// 也可以是 Sprite / MovieClip 坐标,鼠标坐标,等等。
dx = x2 – x1;
dy = y2 – y1;
dist = Math.sqrt(dx*dx + dy*dy);

颜色组合:

1.color24 = red < < 16 | green << 8 | blue;
2.color32 = alpha << 24 | red << 16 | green << 8 | blue;

颜色提取:

1.red = color24 >> 16;
2.green = color24 >> 8 & 0xFF;
3.blue = color24 & 0xFF;
4.alpha = color32 >> 24;
5.red = color32 >> 16 & 0xFF;
6.green = color32 >> 8 & 0xFF;
7.blue = color232 & 0xFF;

穿过某点绘制曲线:

1.// xt, yt 是我们想要穿过的一点
2.// x0, y0 以及 x2, y2 是曲线的两端
3.x1 = xt * 2 – (x0 + x2) / 2;
4.y1 = yt * 2 – (y0 + y2) / 2;
5.moveTo(x0, y0);
6.curveTo(x1, y1, x2, y2);

角速度转换为 x, y 速度:

1.vx = speed * Math.cos(angle);
2.vy = speed * Math.sin(angle);

角加速度(作用于物体上的 force)转换为 x, y 加速度:

1.ax = force * Math.cos(angle);
2.ay = force * Math.sin(angle);

将加速度加入速度:

1.vx += ax;
2.vy += ay;

移除出界对象:

1.if(sprite.x - sprite.width / 2 > right ||
2.sprite.x + sprite.width / 2 < left ||
3.sprite.y – sprite.height / 2 > bottom ||
4.sprite.y + sprite.height / 2 < top){
5.// 删除影片的代码
6.}

重置出界对象:

1.if(sprite.x - sprite.width / 2 > right ||
2.sprite.x + sprite.width / 2 < left ||
3.sprite.y – sprite.height / 2 > bottom ||
4.sprite.y + sprite.height / 2 < top){
5.// 重置影片的位置和速度
6.}

屏幕环绕出界对象:

01.if(sprite.x - sprite.width / 2 > right){
02.sprite.x = left - sprite.width / 2;
03.}else if(sprite.x + sprite.width / 2 < left){
04.sprite.x = right + sprite.width / 2;
05.}if(sprite.y – sprite.height / 2 > bottom){
06.sprite.y = top – sprite.height / 2;
07.}else if(sprite.y + sprite.height / 2 < top){
08.sprite.y = bottom + sprite.height / 2;
09.}

摩擦力应用(正确方法):

01.speed = Math.sqrt(vx * vx + vy * vy);

02.angle = Math.atan2(vy, vx);
03.if(speed > friction){
04.speed -= friction;
05.}else{
06.speed = 0;
07.}
08.vx = Math.cos(angle) * speed;
09.vy = Math.sin(angle) * speed;

摩擦力应用(简便方法):

1.vx *= friction;
2.vy *= friction;

简单缓动运动:

01.//长形
02.var dx:Number = targetX - sprite.x;
03.var dy:Number = targetY - sprite.y;
04.vx = dx * easing;
05.vy = dy * easing;
06.sprite.x += vx;
07.sprite.y += vy;
08.//中形:
09.vx = (targetX - sprite.x) * easing;
10.vy = (targetY - sprite.y) * easing;
11.sprite.x += vx;
12.sprite.y += vy;
13.//短形:
14.sprite.x += (targetX - sprite.x) * easing;
15.sprite.y += (targetY - sprite.y) * easing;

简单弹性运动:

01.//长形
02.var ax:Number = (targetX - sprite.x) * spring;
03.var ay:Number = (targetY - sprite.y) * spring;
04.vx += ax;
05.vy += ay;
06.vx *= friction;
07.vy *= friction;
08.sprite.x += vx;
09.sprite.y += vy;
10.//中形:
11.vx += (targetX - sprite.x) * spring;
12.vy += (targetY - sprite.y) * spring;
13.vx *= friction;
14.vy *= friction;
15.sprite.x += vx;
16.sprite.y += vy;
17.//短形:
18.vx += (targetX - sprite.x) * spring;
19.vy += (targetY - sprite.y) * spring;
20.sprite.x += (vx *= friction);
21.sprite.y += (vy *= friction);

偏移弹性运动:

1.var dx:Number = sprite.x - fixedX;
2.var dy:Number = sprite.y - fixedY;
3.var angle:Number = Math.atan2(dy, dx);
4.var targetX:Number = fixedX + Math.cos(angle) * springLength;
5.var targetY:Number = fixedX + Math.sin(angle) * springLength;
6.// 如前例弹性运动到 targetX, targetY

距离碰撞检测:

01.// 从影片 spriteA 和 spriteB 开始
02.// 如果使用一个空白影片,或影片没有半径(radius)属性
03.// 可以用宽度或高度除以 2。
04.var dx:Number = spriteB.x - spriteA.x;
05.var dy:Number = spriteB.y - spriteA.y;
06.var dist:Number = Math.sqrt(dx * dx + dy * dy);
07.if(dist < spriteA.radius + spriteB.radius){
08.// 处理碰撞
09.}

多物体碰撞检测:

01.var numObjects:uint = 10;
02.for(var i:uint = 0; i < numObjects - 1; i++){
03.// 使用变量 i 提取引用
04.var objectA = objects[i];
05.for(var j:uint = i+1; j{
06.// // 使用变量 j 提取引用
07.var objectB = objects[j];
08.// perform collision detection
09.// between objectA and objectB
10.}
11.}

坐标旋转:

1.x1 = Math.cos(angle) * x - Math.sin(angle) * y;
2.y1 = Math.cos(angle) * y + Math.sin(angle) * x;

反坐标旋转:

1.x1 = Math.cos(angle) * x + Math.sin(angle) * y;
2.y1 = Math.cos(angle) * y - Math.sin(angle) * x;

动量守恒的 ActionScript 表达式,短形:

1.var vxTotal:Number = vx0 - vx1;
2.vx0 = ((ball0.mass - ball1.mass) * vx0 + 2 * ball1.mass * vx1) /
3.(ball0.mass + ball1.mass);
4.vx1 = vxTotal + vx0;

万有引力:

01.function gravitate(partA:Ball, partB:Ball):void{
02.var dx:Number = partB.x - partA.x;
03.var dy:Number = partB.y - partA.y;
04.var distSQ:Number = dx * dx + dy * dy;
05.var dist:Number = Math.sqrt(distSQ);
06.var force:Number = partA.mass * partB.mass / distSQ;
07.var ax:Number = force * dx / dist;
08.var ay:Number = force * dy / dist;
09.partA.vx += ax / partA.mass;
10.partA.vy += ay / partA.mass;
11.partB.vx -= ax / partB.mass;
12.partB.vy -= ay / partB.mass;
13.}

余弦定理:

1.A = Math.acos((b * b + c * c - a * a) / (2 * b * c));
2.B = Math.acos((a * a + c * c - b * b) / (2 * a * c));
3.C = Math.acos((a * a + b * b - c * c) / (2 * a * b));

基本透视法:

1.scale = fl / (fl + zpos);
2.sprite.scaleX = sprite.scaleY = scale;
3.sprite.alpha = scale; // 可选
4.sprite.x = vanishingPointX + xpos * scale;
5.sprite.y = vanishingPointY + ypos * scale;

Z 排序:

1.// 假设有一个带有 zpos 属性的 3D 物体的数组
2.objectArray.sortOn("zpos", Array.DESCENDING | Array.NUMERIC);
3.for(var i:uint = 0; i < numObjects; i++){
4.setChildIndex(objectArray[i], i);
5.}

坐标旋转:

1.x1 = cos(angleZ) * xpos - sin(angleZ) * ypos;
2.y1 = cos(angleZ) * ypos + sin(angleZ) * xpos;
3.x1 = cos(angleY) * xpos - sin(angleY) * zpos;
4.z1 = cos(angleY) * zpos + sin(angleY) * xpos;
5.y1 = cos(angleX) * ypos - sin(angleX) * zpos;
6.z1 = cos(angleX) * zpos + sin(angleX) * ypos;

3D 距离:

1.dist = Math.sqrt(dx * dx + dy * dy + dz * dz);

本文来自: Flash-一些常用物理公式和AS3的结合应用

Flash Player 10 中的RTMFP协议(实现P2P技术)

<Category: RTFMP协议> 发表评论

         RTMFP是Adobe公司开发的一套新的通信协议,该协议可以让使用Adobe Flash Player的终端用户之间进行直接通信。用Adobe AIR框架开发的程序也可以用此协议来发布直播、实时信息。 

  通过使用RTMFP, 那些以来直播、实时通信的应用,比如社区、音视频聊天和多人游戏就有能力来发布高质量的通信解决方案。RTMFP让终端用户可以直接连接并通信,可以使用麦克风和摄象头直接聊天。RTMFP将不支持文件和文档共享。此方案提升了目前Flash Player在网络交互方面的体验。 

    RTMFP将减少直播、实时聊天方案的带宽消耗,例如音视频聊天和多人游戏。因为TRMFP的数据在终端用户之间流动,而不是和服务器,所以此方案很适合于大范围的部署。RTMFP因为采用了UDP也提升了传送的速度。UDP是Internet上一种更有效传送音频视频的方法,虽然会有一些丢包,错包。RTMFP有两个特性可以帮助解决一些连接错误。

  快速连接恢复:连接在以外情况下将快速恢复。例如,一个无线连接掉线了,一旦重连,他将迅速拥有所有的传送能力。

    IP动态化:一个活动的网络会话将以PEER来标识,即使他变了一个IP,也可以保持原来的会话。例如,一个笔记本在一个无线网络获得了一个新IP地址,他将立刻继续刚才的会话。 

    RTMP和RTMFP之间的不同。

  最基本的确实是他们在网络上采用的协议。RTMFP是基于UDP的,RTMP是基于TCP的。UDP在传送直播数据方面比TCP还是有较多优势的,比如减少延时,对丢包的容忍,虽然在可靠性上有所损失。不象RTMP, RTMFP支持Flash Player直接发送数据给另一个,而不经过Server。服务端连接将被用来初始化并交互一些客户端之间的信息,也可用来进行服务端调用或者作为进入其他系统的网关。FMS也将用来为用户提供地址认证服务和NAT地址转换服务,避免用户陷入混乱。


本文来自: Flash Player 10 中的RTMFP协议(实现P2P技术)

完整的 AIR 2.0 新特性中文详细介绍

<Category: ActionScript 3.0, Adobe, Flash, Flex, Flex3, Flex4> 发表评论

新功能

File Promises
        File promises 是一个新的API(URLFilePromise)。要从AIR应用程序下载文件,用这个API十分方便。因为你只需把文件的URL从AIR程序窗口拖出到本机上,文件就会开始下载。效果就像你需要从QQ共享里下载文件一样,把它拖到桌面上,文件便会自动下载到你的桌面上。

var items:Array = fileData.selectedItems;
var promises:Array = new Array();
for each (var item:Object in items)
{
        var filePromise:URLFilePromise = new URLFilePromise();
        var request:URLRequest = new URLRequest(item.url);

        filePromise.request = request;
        filePromise.relativePath = item.name;
        promises.push(filePromise);
}

clipboard.setDate(ClipboardFormats.FILE_PROMISE_LIST_FORMAT, promises);
NativeDragManager.doDrag(fileDate, clipboard);

屏幕阅读器(Screen reader)
        从前AIR里的文字是不被屏幕所认知的。AIR 2.0 终于可被屏幕阅读了。什么意思呢?我想应该就像金山词霸的“屏幕取词”功能一样,你把鼠标放在AIR里的文字上,就可以使用金山词霸来翻译了(现在我是用灵格斯的“剪贴板取词”)。不过,在此版本只支持 Windows 操作系统。以下特性已经添加:

  • 运行时对话框—对话框可被屏幕阅读器阅读了;
  • Flex组件和窗口—Flex组件和窗口可被屏幕阅读器阅读了;

本地进程(应用程序)
        与使用默认应用程序打开文件类似,AIR 2.0 可以运行本地进程并且与它进行交互。这个新特性只适用于应用程序是用本地系统安装程序安装的情况下。以下类已被支持:

  • flash.desktop.NativeProcess — 集成了命令行并且可在本机运行。当某个进程运行后,AIR应用程序可以监听它的输入数据、输出数据以及错信息;
  • flash.desktop.NativeProcessStartupInfo — 提供了在本机启动一个进程所需的基本信息;
  • flash.events.NativeProcessExitEvent — 当进程退出时调度此事件。这个事件有可能不会被调度,当子进程比AIR应用程序的生命周期要长时。

新的网络支持

  • IPv6 支持
    AIR 2.0 对所有网络API新增了IPv6的支持。目前互联网大多数在使用IPv4,它已经有20历史了。
  • 用户数据报协议
    在已有的Socket类之上添加了新的socket类。已有的类支持TCP协议,而在AIR 2.0里新增了 DatagramSocket 类以支持UDP协议。DatagramSocket 类允许发送和接收 UDP 数据包。

 

增强功能的API

NativeWindow 的最大尺寸
        在 AIR 1.5.2 时代 NativeWindow 的最大尺寸是 2880×2880 像素,而在 AIR 2.0 里将提升到 4095×4095 像素。

空闲超时
        允许设置空闲超时值(只支持win/Mac)。

Mac上的矢量印刷
        AIR 1.5 在 Windows 上支持了矢量印刷(flash.printing.PrintJob)。AIR 2.0 将会在 Mac 上支持这特性。

数据库的业务保存点
        在 AIR 1.5 里,SQLConnection 类支持业务(transactions)。业务允许用户跟踪SQL命令并在需要时提交或退回。AIR 2.0 里新增了这些方法:savepoints()、setSavepoint()、releaseSavepoint()以及rollbackToSavePoint()。

麦克风访问API
        AIR 2.0 提供了可以访问未压缩的PCM字节数据的麦克风API了。具体查看手册里的 SampleDataEvent.SAMPLE_DATE 事件。

使用默认应用程序打开文件
        新增了 openWithDefaultApplication() 方法,可使用系统的默认应用程序打开文件。当你使用此方法时,文件会被已在系统上注册了的默认应用程序打开。如果文件是可执行文件(例如:*.exe),那么它会直接执行。

跟平台有关的APIs

多点触摸功能
        MultitouchInputMode 是一个枚举类,存放着三种多点触摸硬件类型:

GETTURE = “getture”
NONE = “none”
TOUCH_POINT = “touchPoint”

首先你需要设置 Multitouch 类的硬件类型,然后你就可以开始监听事件了。

存储器(Storage Volume)监听
        Adobe 说:真失策,在以往的版本里居然遗漏了这个功能。AIR 2.0 提供了对系统的存储器信息访问和监听的API。通过这些API,你不仅可以访问到硬盘文件系统,同时还可以监听通过USB或火线进行连接的移动存储设备,例如移动硬盘和以存储方式连接到计算机的相机,MP3或手机等等。这两个类可以帮到你:

  • flash.filesystem.StorageVolumeInfo—这个 StorageVolumeInfo 类是一个单例管理类,有两种事件类型:storageVolumeMount 和 storageVolumeUnmount;
  • flash.filesystem.StorageVolume—这个类存放着跟存储器有关的属性信息;

 

更好的性能

减小资源开销
        AIR 应用程序被大众认定是占用资源的。在 AIR 2.0 里,Adobe 付出了额外的努力去减小运行时的体积,减小CPU/内存的消耗。

WebKit的性能
        使用了更新的 WebKit ,性能加快了,还提供更多功能。详细:点击这里

更多报道…

本文来自: 完整的 AIR 2.0 新特性中文详细介绍

AdjustDisplayObject 类库新增scale9()和scaleInBox()函数

<Category: ActionScript 3.0, Adobe, Flash, Flex> 发表评论

DisplayObjectTransformer.scale9()

        对点阵图(Bitmap)进行九切片缩放(flash自身不支持对位图进行九切片缩放的)。假如未指定 scale9Grid 参数,将采用 Bitmap.scale9Grid 的值来进行缩放。如下所示

scale9_exmaple

参数

  • target:Bitmap — 需要进行九切片缩放的 Bitmap 对象。
  • newWidth:Number — 新宽度,如不想改变宽度,请将原值传递进来。
  • newHeight:Number — 新高度,如不想改变高度,请将原值传递进来。
  • scale9Grid:Rectangle (default = null) — 缩放网格。

 

DisplayObjectTransformer.scaleInBox()

        等比缩放。保持原有宽高比,对显示对象进行缩放。适用于以下情况:你想把某一张图片缩放到指定大小的区域里,而且保持原有的宽高比,不进行拉伸。如下图所示:

scaleInBox_exmaple

参数

  • target:DisplayObject — 要进行等比缩放的显示对象。
  • boxWidth:Number — “盒子”宽度。
  • boxHeight:Number — “盒子”高度。

 

源码和例子下载

本文来自: AdjustDisplayObject 类库新增scale9()和scaleInBox()函数

采用AIR开发的事务管理应用:Doit.im

<Category: RIA应用案例, 游戏应用> 发表评论

引用官网上的介绍:

        Doit.im 采用优秀的任务管理理念,引导您将脑袋清空,使您免受头脑中各种漂浮想法的干扰,有条不紊地组织规划各项任务,以集中注意力完成重要事项,将工作节奏牢牢把握在手中,轻松应对各项庞大繁杂的工作,在感受无压工作乐趣的同时,畅享高效工作的成就感!

还提出了“GTD”概念 (get things done,完成每一件事)。界面不错,交互可以,未来也会推出手机版的。但对于作为开发者的我来说,不知道为什么,肯定是试用后就不会再用了。我觉得,这类大众软件要做到让用户天天用、时时刻刻在用,软件越短小精悍越好。

网址http://doit.im/

本文来自: 采用AIR开发的事务管理应用:Doit.im

Machinarium 是一款出色的 Flash 益智游戏

<Category: 游戏应用> 发表评论

这款游戏不但人物形象设计独特,画质一流,连动画也是非常有趣且出色的。剧情令人耐人寻味,一些益智小游戏穿插其中。在玩这款游戏时,感觉像是在看卡通片,而且这套卡通片给人很强的艺术感。就像当我第一次看到舍友在玩“生化危机5”时,给我的感觉就是在看电影,一套3D的电影,一套可由观众操控的电影,多有趣!

        可惜是单机版,固定的剧情决定了这游戏是玩不久的。通常,玩完第一次就不会有第一次,除非打不通关而你还有恒心。在线的是试玩版,verycd 上有完整的破解安装版。

网址http://machinarium.net/

本文来自: Machinarium 是一款出色的 Flash 益智游戏

Flash Professional CS5 beta什么时候才可以正式下载使用

<Category: ActionScript 3.0, Adobe, Flash> 2 条评论

据Adobe官方消息声称 Flash Professional CS5 beta会在2009年年底一直发布并下载使用

When will the Flash Professional CS5 beta be available for download?
The beta will be available for download from Adobe Labs before the end of 2009.

本文来自: Flash Professional CS5 beta什么时候才可以正式下载使用

深入分析Flex [Bindable] 以及使用方法

<Category: Adobe, Flex, Flex3, Flex4> 发表评论

[Bindable]大概又是Flex用得最多的元数据了。刚开始用用确实好简单,效率真是没的说。不过这几天用着却碰到了些问题,我自己搜集了些资料,想着有必要在blog里总结一下吧。
啥是元数据(metadata)

知道就跳过吧。今天不晓得为什么livedoc.adobe.com这么慢,没办法,拿不到权威的解释了。我就按自己的理解随便解释一下:首先要明白元数据不是语法的一部分,而是专门给编译器用的,说白了是告诉编译器做某些事情,学过java之类的应该知道。那Bindable来讲,它的作用是告诉 flex编译器,给某些某些东西建立绑定关系,flex编译器会在编译过程中给AS(flex编译器就是把mxml编译成as,再编译到swf,也可能直接编译倒swf,我这里假设有as这么个环节)加一点事件发生和处理之类的代码,由此绑定的关系便建立了,如果我们用纯粹as3代码来写也是可以实现的,就是太太太麻烦。
啥是绑定

知道继续跳过。举个例子:给下面的public变量加上[Bindable]

[Bindable]
public var name:String = ”";

作为一个public变量,肯定既可以被赋值,也能赋值给别的变量。绑定的作用就是,当name改变的时候(被赋值了),可能通知其它被name影响(赋值给它们)的变量发生改变。这里的“可能”就需要编译器来判断,这就是为什么元数据是给编译器用的原因了。在mxml里用{}的语法的地方就是绑定的对象,比如label={xxx.name},当name变化,label也跟着变化。这样,我们只是很简单的改变了name的值,由于有绑定,界面上的label也跟着自动变化了,爽吧。
能用在哪里

三个地方:类, 变量, getter/setter。是不是public没有关系,private的就只能给自家用呗。用在Class上就是简单的给所有的public属性(包括变量,getter/setter,普通方法)加上[Bindable],可是一般的方法不能用[Bindable]呀,于是一般就能看到flex给了个warning,直接无视:)。变量嘛就是上面讲的,很简单略掉。
用在只读,只写属性(getter/setter)上面

终于讲到关键地方了,因为getter和setter很像方法,用起来会有点不同。看看这个例子:

[Bindable]
private var content:Array = new Array();
[Bindable]
public function set _content(ct:String):void
{
       content = ct.split(SEP);
}
[Bindable]              
public function get _wholeText():String
{
       if(content.length == 0)
       {
              return ”";
       }
       else
       {
              var _w:String = ”";
              for(var i:int=0 ; i<content.length ; i++)
              {
                     _w += content[i] + ”\r\n”;
              }
              return _w;
       }
}

原来的设想是content绑定_wholeText,可它是不工作的。为什么?_wholeText太复杂了,被编译器排除在“可能”之外,编译器认为没有绑定关系,如果只是简单的return content,倒是可以的。我这里搜到了一些比较权威的解释。来自http://www.rubenswieringa.com/blog/binding-read-only-accessors-in-flex找到Ely Greenfield讲的。

Now keep in mind that there’s no way for the compiler to actually tell if the value of a property get function would be different if called, short of doing an extensive code flow analysis of the get function, identifying all the inputs that might be affecting the value of the get function (i.e., member fields, statics, globals that are used in the get function and in any methods, global functions, closures, etc) it might call, and setting up watchers on every one of those to trigger the binding when any of them change. That’s prohibitively difficult, and expensive to do. So the compiler doesn’t try.

Instead when you put [Bindable] on a get/set property, the compiler makes it bindable with a little creative rewriting that allows the framework to watch the get function, and dispatch a change event when the get function is triggered. This means that automatic bindable properties don’t work when the get function is computed from multiple values, or when you change its value by setting a backing field, rather than using the set function.

It _also_ means that if you have no set function, we can pretty much guarantee that there’s no way automatically bindable get properties will be triggered. a read only propeerty is, to the compiler, completely opaque…at the moment, it has no idea where that value is coming from, and hence will never be able to ‘automatically’ trigger the binding.

说白了就是为了降低复杂度和提高效率,复杂情况的getter会被忽略。如何解决?可以手动建立绑定,即[Bindable("eventName")]。把代码改成这样:

[Bindable]
private var content:Array = new Array();
[Bindable]
public function set _content(ct:String):void
{
       content = ct.split(SEP);
        this.dispatchEvent(new Event(“_contectChanged”));
}
[Bindable("_contectChanged")]              
public function get _wholeText():String
{
       if(content.length == 0)
       {
              return ”";
       }
       else
       {
              var _w:String = ”";
              for(var i:int=0 ; i<content.length ; i++)
              {
                     _w += content[i] + ”\r\n”;
              }
              return _w;
       }
}

这样就避免了编译器去自动识别。自己加上绑定关系,当_content被赋值,发出_contentChanged事件,通知所有被绑定的getter方法执行一遍。这也说明了,绑定不过是事件游戏而已,flex为用户隐藏了很多底层算法。

本文来自: 深入分析Flex [Bindable] 以及使用方法