我似乎反复的在讲共享对象了,实在是我觉得共享对象在FlashCom开发中太重要了,甚至可以说是FCS的灵魂。
之前的关于共享对象的文章可以参考我的笔记:
共享对象概述
理解共享对象
还有一篇转载的:共享对象
shared Object对象相当强大,他提供了在多个客户端实时数据共享,并且可以存储在客户端或远程服务器。可以把本地共享对象比作cookies,把远程共享对象看作实时的数据传输设备。
通常共享对象的使用方法如下:
1. 保持本地永久存储
这是最简单的共享对象应用。并且不需要FlashCom Server的支持。例如,你可以使用SharedObject.getLocal方法来创建一个本地共享对象。因为本地共享对象是永久存储的,用户端 Flash结束的时候会通过data属性保存在客户端本地机器中。当下一次运行swf文件的时候,就可以直接存取到。如果你在影片播放结束的时候把共享对象的属性置空了,下一次就存取不到任何的值了。
2. 在服务器端共享和存储数据
存储在服务器端的共享对象数据可以被其它联机的客户端取到。例如,你打开了一个远程共享对象,该共享对象中存储了一个电话清单。当客户端对该共享对象数据有任何更改的时候,改变的数据对所有联机对象都是自同步的。如果对象暂时无法连接到服务器端,那么所作的更改将会在下一次更新到服务器端。
3. 实时交流数据
共享对象可以实时的在多个客户端之间共享数据。你可以打开一个存储实时数据的远程共享对象,例如,一个连接到聊天室的用户列表,当有用户进入或离开聊天室的时候,该共享对象会实时更新,所有连接到该服务器的客户端将立刻看到用户列表的更改。
下面的例子演示了一个简单的共享对象的使用,记住在创建一个远程共享对象之前,必须先使用NetConnect对象联机到服务器。
01 : // Create a local shared object
02 : so = SharedObject.getLocal('foo');
03 : // Create a remote shared object that is not persistent on the server
04 : nc = new NetConnection();
05 : nc.connect('rtmp://server.domain.com/chat/room3';
06 : so = SharedObject.getRemote('users', nc.uri);
07 : so.connect(nc);
08 : // Create a remote shared object that is persistent on the server
09 : // but not on the client
10 : nc = new NetConnection();
11 : nc.connect('rtmp://server.domain.com/chat/room3';
12 : so = SharedObject.getRemote('users', nc.uri, true);
13 : so.connect(nc);
14 : // Create a remote shared object that is persistent on the server
15 : // and on the client
16 : nc = new NetConnection();
17 : nc.connect('rtmp://server.domain.com/chat/room3';
18 : so = SharedObject.getRemote('users', nc.uri, '/chat');
19 : so.connect(nc);
规划远程共享对象
要规划远程共享对象,我们应该先设计一个数据管理模型。我们需要做的是数据字段设计和管理、冲突解决、客户端和服务器端的存储分析,我们针对这些方面一一说明。
如果要使用本地存储的远程共享对象,请确保swf的舞台尺寸大于215×138像素,否则将无法正常显示设置面板。
数据设计和管理
共享对象关联的数据存储在共享对象的data属性中,要设置共享对象的值可以使用下面的方式:
1 : //建立本地共享对象,没有则自动创建
2 : var so = SharedObject.getLocal('local_so');
3 : //为共享对象中的变量赋值
4 : so.data.userID = 'Liu21st';
5 : so.data.currentStatus = 'onLine';
6 : so.data.lastLogon = '2004-06-30';
如果要创建客户端的私有存储,可以不通过data属性,如:
1 : so.userID = 'Liu21st';
2 : so.currentStatus = 'onLine';
3 : so.lastLogon = '2004-06-30';
对共享对象的data属性赋NULL或undefined可以初始化字段
so.data.userID = NULL ;
但是并没有删除该字段,如果要删除请用:
delete so.data.userID;
我们也可以使用类似于
so.data.year.month.dayOfMonth = someValue;的方式来赋值
//注意该赋值并非一个字段 year.month.dayOfMonth
//而分别是给三个字段 year,month,dayOfMonth 初始化相同的值
但是不推荐使用该方式,因为这样在同步的时候会始终占用较多的带宽
使用分开赋值的方式可以避免每次同步全部数据
so.data.year = someValue;
so.data.month = someValue;
so.data.dayOfMonth = someValue;
你可以根据应用程序的需求来设计共享对象的变量。如果共享对象中的值都需要频繁更新,尽可能减少共享对象的字段可以提高性能。
站长经常使用的方式是:
1 : so.data.user = { id:1,sex:b,name:liu21st }
2 : // 在存取的时候可以使用
3 : // so.data.user.name的方式
冲突解决
如果多个客户端在同时更新数据的话,冲突就产生了。必须制定冲突解决策略,下面是常用的方法。
1. 尽量使用不同的字段
最简单的方法是给每个客户端或服务器端分配不同的字段。例如,为聊天室中的每个用户设定一个字段,并且每个用户只能更改自己的字段。
2. 分配拥有者
更高级的策略是分配一个客户端作为共享对象属性的短期拥有者,你可以锁定对象的属性被写入,在有其它客户端对该属性的更新时候向拥有者发送请求。如果请求成功,表示只有一个客户端更改该共享对象数据。
3. 通知客户端
当服务器拒绝客户端的更改请求的时候,SharedObject.onSync事件会通知客户端该更改暂时被拒绝,然后,应用程序可以提供一个用户界面让用户再次发送。这个策略比较适用于不定期更新的数据,还有一个好处是当冲突发生时,客户端可以选择接收或拒绝更改。
4. 选择性更改
某些应用程序按照“先到先服务”的原则来定制策略,这种方式适用于用户可以重新递交同步请求当其他人更新完成之后。
本地存储空间的考虑
你可以选择让远程共享对象存储在客户端、服务器或者两者,本地共享对象总是存储在本地客户端,直到没有可用空间为止。
默认的存储空间大小是100K,如果企图存储更多的数据,Flash会弹出一个本地存储对话框,让用户允许或拒绝本地存储。
如果用户选择允许,数据将被保存,并且SharedObject.onStatus事件触发,返回的code属性值为 SharedObject.Flush.Success,如果选择拒绝,数据存储失败,code属性值为SharedObject.Flush.Failed,用户也可以选择打开本地存储面板,进行存储空间大小设置,并且记住当前的选择。
在actionscript中无法设置本地存储空间的大小,必须通过弹出对话框的形式让用户操作,如果需要,请使用:
System.showSettings(1)
共享对象的方法总结
SharedObject.close
//关闭远程共享对象和服务器的连接
SharedObject.connect
//连接到服务器端的一个远程共享对象
SharedObject.flush
//立即写入本地共享对象数据
//如果不使用系统会在下列情况自动完成写入
// swf文件关闭,sharedObject.close调用,共享对象被回收
// 如果对远程共享对象使用该方法,只会在客户端写入,而不会在服务器端写入,如果要完成服务器端的写入请使用下面的代码:
01 : // This is a SERVER-SIDE script, not ActionScript
02 : // Get the shared object when the application is loaded.
03 : application.onAppStart = function()
04 : {
05 : application.mySO = SharedObject.get( 'SharedObjName' , true);
06 : }
07 : // When a user disconnects, flush the shared object.
08 : application.onDisconnect = function(client)
09 : {
10 : application.mySO.flush();
11 : }
12 : // You can also set a timer to periodically flush the shared object
13 : // onto the hard disk on the server
14 : application.onAppStart = function()
15 : {
16 : application.mySO = SharedObject.get( 'SharedObjName' , true);
17 : setInterval(function() { application.mySO.flush(); }, 60000);
18 : }
SharedObject.getRemote
//创建一个远程共享对象
SharedObject.getSize
//取得当前(本地或远程)共享对象的字节大小
//var soSize= this.so.getSize();
SharedObject.send
//对所有联机用户广播消息
01 : // Create a remote shared object called remoteSO
02 : // Place an Input Text text box named inputMsgTxt on the Stage
03 : // Attach this code to a button labeled 'Send Message'
04 : on (release) {
05 : _root.remoteSO.send( 'testMsg' ,inputMsgTxt);
06 : }
07 : // Attach this code to the frame containing the button
08 : _root.remoteSO.testMsg = function(recvStr)
09 : {
10 : trace(recvStr);
11 : }
12 : // Type data in the text box and press the button to see the results
SharedObject.setFps
//设定客户端更新的速率
共享对象的创建方法
SharedObject.getLocal(对象名称);//不需要服务器端支持,只用于本地存储
01 : // Get the kookie
02 : so = sharedobject.getlocal( 'kookie' );
03 : // Get the user of the kookie and go to the frame number saved for this user.
04 : if (so.data.user != undefined) {
05 : this.user = so.data.user;
06 : this.gotoAndStop(so.data.frame);
07 : }
08 : The following code block is placed on each movie frame.
09 : // On each frame, call the rememberme function to save the frame number.
10 : function rememberme() {
11 : so.data.frame=this._currentFrame;
12 : so.data.user= 'John' ;
13 : }
SharedObject.getRemote(对象名称,联机网址);//建立暂存的远程共享对象,重启即失效
1 : conn = new NetConnection();
2 : conn.connect( 'rtmp://somedomain.com/applicationName' );
3 : myObject = SharedObject.getRemote( 'mo' , conn.uri, false);
4 : myObject.connect(conn);
SharedObject.getRemote(对象名称,联机网址,true);//远程共享对象数据存入服务器,在服务器端会保存'对象名称.fso'文件
共享对象的属性
data属性(不再详述)
共享对象的方法
共享对象的事件
SharedObject.onStatus //共享对象返回错误、警告或状态的事件
SharedObject.onSync //同步事件
下面的实例可以参考:
01 : function getMaster()
02 : {
03 : trace( 'getMaster called' );
04 : master = SharedObject.getRemote( 'master' , con.uri, true);
05 : connVal = master.connect(con);
06 : if (connVal) print ( 'Connection was successful' );
07 : else print( 'Unable to connect the shared object with the given NetConnection object' );
08 : master.onSync = function (listVal) {
09 : getPlayList();
10 : trace( 'SO: ' + so.data[currentPlaylist]);
11 : }
12 : }