Flash之共享---SharedObjects Flash之共享---SharedObjects

来源:互联网 发布:安卓 java ide 编辑:程序博客网 时间:2024/05/16 11:54

Flash的一个重要的特征就是SharedObject.在最基础的功能中,SharedObject被设计成为一种巧妙的装置,它允许在用户的本地系统中存贮用户的相关数据。它的机制和cookie相似,而比cookie功能更好。如果你还没有想出本地存储数据的訽因、用途,那就是你还没有仔细的思考过。下面的例子中,将会使用到一个SharedObject(SO 下同)来确定某个用户是否已綺登录过你的站点-如果已綺登录过,或许可以允许用户在浏览的时候自动地跳过网站的片头动籣。当然还有更多的复杂、酷的应用。

首先要注意的是,在Flash中,SO是可以在客户端被禁用的。显然,这将会立即防碍我们的应用,下面的代码将会检查在用户的系统中SO能否使用:

function checkSO() {
// Does this client allow SharedObjects to be stored?
// Create a dummy SO and try to store it
mySO = SharedObject.getLocal("test");
if (!mySO.flush(1)) {
// SOs not allowed on this system!
// Prompt user to change settings
System.showSettings(1);
} else {
// SOs allowed
trace("Your system allows SharedObjects");
}
}
checkSO();

别着急,我将不会使你陷入困境,上面的代码再开始的时候是很重要的。在开始之前,把代码放在新movie的一个关键键帧上,并且运行它来确信你的系统支持、允许SO。(也要注意,上面的代码仅仅是检查你自己的系统对1byte大小的SO的支持情况,所以如果你想使它对任何其他的用法也适应的话,那么检查这个特征是处于启用或者是关闭状态,切记。)

让我们以商业的角度来看一下Object是什么。Object是一种用来很好的分类存储(一般说法)数据的方法。所以如果我们有100个客户的话,我们不会使用下面的方式存储信息:

Cust1Name = "Joe";
Cust1Age = 20;
Cust1Pet = "Dog";
Cust2Name = "Mary";
Cust2Age = 19;
Cust2Pet = "Dog";
...

我们使用object(对象)来规划:

Cust1 = new Object();
Cust1.name = "Joe";
Cust1.age = 20;
Cust1.pet = "Dog";
...

我们创建一个新的SharedObject:

mySO = SharedObject.getLocal("test");

我们也使用这句代码来获得已经保存过的SO。在这里,"mySO"是对象名,我们将会在Flash中引用,而"test"是指定给系统的文件名。SO存储在本地,文件的缺省扩展名是".sol"。注意文件名可以包含前斜杠("/"),但是大多数的特殊字符不允许使用,他们包括~ 、%、&、/、;、:、"、'、< >、?、#和空格键。

当创建好SO后,倘若你没有删除它,那么你就可以使用flush方法把它写进用户的硬盘。flush方法返回值true、false和"pending"。返回的布尔值如果是true,表示写操作已经成功;如果是false,表示写操作不成功。等会儿我们将处理返回值"pending"。在硬盘上的文件只有使用flush方法的时候才能对它进行创建、修改操作。

mySO = SharedObject.getLocal("test");
mySo.data.name = "Joes";
success = mySO.flush();

flush有一项可选的参数,就是你想要存储在硬盘上的数据大小,我们可以通过mySO.getSize()方法来指定被允许存储的SO的最大数据量。Flash MX不仅可以让“终端”用户确定是否允许使用SharedObjects,而且也能够让用户控制、分配硬盘空间给SharedObjects,缺省设置允许SharedObjects在硬盘上的存储数据量为100K。如果你打算在任何的场景写入的数据量比用户的系统允许的还要多,那么用户会看见一个即时弹出的提示消息(见下图,Figure 1.1)。当这样的一个提示消息被flush方法触发的时候,将会返回一个字符串"pending",而不是true或false。我们现在可以看见上面例子,当试图检查写操作是否成功而出现的问题的时候,变量success会产生出"pending"(通过一个条件语句)。下面将解决这个问题。


Figure 1.1

当flush方法返回值的时候,新的事件模式允许我们触发一个函数。函数通过SharedObject.onStatus方法来定义,当flush操作,向用户要求更多的磁盘空间,解决之后将会触发这个函数。注意,当flush处于pending状态(等待用户授权写操作),以及用户还没有从磁盘空间设置界面退出的时候,都不会触发函数。如果我们将写入用户硬盘1k的数据,而客户端(client)允许10k的空间,那么onStatus函数将不会被调用。当被调用的时候,函数会被传递一个对象,指示操作是否成功。Macromedia格式的文档提出这个对象包含一个类的属性和一个代码属性,但是经过我的测试发现,实际上包含了一个level(层)属性,而不是类的属性。当要求额外的磁盘空间操作成功的时候,将会返回一个对象,带有level属性的字符串"status"和一个代码性的"SharedObject.Flush.Success";当操作不成功的话,会返回level属性的"error" 和代码性的"SharedObject.Flush.Failed"。下面执行一个函数,通过检查onStatus方法的返回值,来成功的测定我们的写操作是否发生了:

mySO = SharedObject.getLocal("test");
mySo.data.name = "Joes";
success = mySO.flush(100000);
if (success == "pending") {
mySO.onStatus = function(result) {
if (result.code == "SharedObject.Flush.Success") {
trace("Sucess writing to disk");
writeSuccess = true;
} else {
trace("Failure writing to disk");
writeSuccess = false;
}
};
} else {
writeSuccess = success;
}

当我们向SO添加数据的时候,可以通过给"data"的子项添加数据,以达到长期在用户的硬盘上保留数据的目的。将信息添加到别处是不必要的。也要注意,只有SO的data子项属性会被写在硬盘上,我的测试表明,如果一个SO的data子项是空的,那么它将不会被保存。 下面的代码在一个过程里面进行了创建一个新的SO,保存这个SO,然后删除它,最后将它重新装载四个步骤。重新装载的时候,我们通过for...in循环来跟踪SO里面的所有的值。注意变量shortLived,它不是data的子项,不是持久的,但是变量stickAround却是。也要注意这些变量所保存的变量类型;没有必要像对待cookies一样把字符型转换成为数据类型。

// Create an SO
mySO = SharedObject.getLocal("test");
// Add some expendible data
mySO.shortLived = "Woe is me, the short lived variable";
// Add some important data
mySO.data.stickAround = "I'll be here for years to come!";
mySO.data.num = 123;
mySO.data.obj = new Array(4, 5, 6, 7);
// Write the SO to the disk (I'm not checking for success here)
mySO.flush();
// Delete the SO
delete mySO;
// Load the SO back in
mySO = SharedObject.getLocal("test");
// Scan the SO for values
for (a in mySO.data) {
trace(a+": "+mySO.data[a]);
}

有意思的是,当你重新装载一个已经存在于硬盘的SO,改变、改写一两个值的时候,原来文件的内容不会被正确的修改。这里我们不采用将新的内容与先前的文件结合的方法,而是修改先前的一些定义,并且保留先前的值不加以更改。你可以尝试运行下面的代码:

// Create an SO
mySO = SharedObject.getLocal("test");
// Add some important data
mySO.data.stickAround = "I'll be here for years to come!";
// Write the SO to the disk (I'm not checking for success here)
mySO.flush();
// Delete the SO
delete mySO;
// Reload the SO
mySO = SharedObject.getLocal("test");
// This time we're not adding any data, so when we write
// our SOit should the old data be overwritten, right?
mySO.flush();
// Delete the SO
delete mySO;
// Load the SO back in once more,
mySO = SharedObject.getLocal("test");
// Scan the SO for values
for (a in mySO.data) {
trace(a+": "+mySO.data[a]);
}
// Wrong! The trace shows our old values all still exist!

很显然这个特征有着一些有用的暗示,当我们因为安全或者是代码整洁的原因,而从SO里面删除一个条目的时候会发生什么事情呢?当然我们能够更改一些数据,但是这样做的后果是,将会在用户的系统中留下一些“垃圾”。上帝保佑,Macromedia也考虑到了这一点。你可以先在Flash里面删除对象的属性,然后再一次的使用flush方法,这么一来就达到了在硬盘上删除SO文件里面数据的目的。感谢来自ActionScript.com的Dave Emberton,当我在下午3点35分和他闲聊的时候,他提供给我了这种删除数据的方法。看看吧,我们为了你们这些人的便利是多么的辛苦啊!

mySO = SharedObject.getLocal("test");
mySO.data.stickAround = "I'll be here for years to come!";
mySO.flush();
delete mySO;
// Reload the SO
mySO = SharedObject.getLocal("test");
delete mySO.data.stickAround;
mySO.flush();
// Delete the SO
delete mySO;
// Load the SO back in once more,
mySO = SharedObject.getLocal("test");
// Scan the SO for values
for (a in mySO.data) {
trace(a+": "+mySO.data[a]);
}
// Wohoo! No stickAround value!

Macromedia文档没有告诉我们怎么从用户的硬盘上删除文件,(尽管他们说这样做是不可能的),但是我们可以通过上面的两个事情看出,首先当我们“写”一个子项没有属性的SO时候,操作将不会成功。然后,当我们从data子项删除一个属性并且重写这个SO的时候,这个属性就被从在硬盘上的文件里面删除了。所以为了删除这个硬盘上的文件,你仅仅需要删除所有data的子项。要达到这种方法,使用一个for...in循环可能是最好的方法了。

// Make a basic SO
mySO = SharedObject.getLocal("test");
mySO.data.stickAround = "I'll be here for years to come!";
mySO.data.myArray = new Array(1, 2, 3, 4);
mySO.flush();
delete mySO;
// Reload the SO
mySO = SharedObject.getLocal("test");
for (a in mySO.data) {
delete mySO.data[a];
}
mySO.flush();
// Delete the SO
delete mySO;
// Load the SO back in once more,
mySO = SharedObject.getLocal("test");
// Scan the SO for values
for (a in mySO.data) {
trace(a+": "+mySO.data[a]);
}
// There are none. There's no file on the drive any more either

It's noteworthy that all the examples I've used in this tutorial cover creating and accessing the SO from the same SWF file. In practice this will rarely be the case, as we like to make our SWF files modular. To access a SO file created by a different SWF file you need to provide additional arguments to the getLocal() method. See this thread in which we show how it's done.值得注意的是,在本教程中我们使用的例子,包含了从同一个swf文件里面创建和存取SO。在实际应用中很少会出现这样的例子,我们只是为了使这个swf文件标准化一些。为了存取、访问一个被其他swf文件创建的SO文件,你需要使用getLocal() 方法并且提供相应的参数。看看下面的这封来自ActionScript.com的技术文章,你会明白怎么去做的。最后,如果为了网络应用的需要,你打算“强制”你的用户接受SO,那么你可以提供给他们你的建议,运行下面的代码:

 

System.showSettings(1);

代码运行时,会出现一个本地设置对话框,允许用户使用或者禁用本地存储,通过一个比例调节拉杆增加或者减少本地存储容量。


Figure 2.1

Viola!感谢Macromedia和他们的产品。我要上床睡觉啦。如果我的这个教程帮助了你,请给我一个email告诉我一声,欢觃提供改正意见和建议。


Jesse Stratford是ActionScript.org的管理者,同时他也是自由作家、Flash开发人员和教师。目前,他居住在澳大利亚,他深爱、陶醉于Flash之中。
作者注: 如果你有你的注解或者是反馈,你可以email给我,但是请不要在email里面提一些有关Flash技术上的问题。我们有着共同的论坛,在那里你可以提出你的问题,并且可以得到满意的答复,谢谢合作。 译者注: 如果你已经安装了Flash Communication Sever MX,你可以看一下安装目录下C:/Program Files/Macromedia/Flash Communication Server MX/flashcom/applications/example_sharedball下面的fla文件,相信可以帮助你更好的理解教程的内容。

 
原创粉丝点击