SharedObject对象FlashCom Develop阅读笔记 (十六)

2006-03-09 00:45:21

我似乎反复的在讲共享对象了,实在是我觉得共享对象在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 : } 以上所言,主要针对客户端对象,服务器端的共享对象使用会在以后的笔记中再详细描述。