AS3 CookBook学习整理(十四)

1. 清除视频显示

调用Video对象的clear()方法

在调用netStream.close()以后,并不会自动清除video显示的内容。视频的最后一帧内容仍显示在Video对象上,需调用video.clear()来进行清除

要从现实列表上删除Video对象需调用removeChild(video)

2. 检测用户带宽

Flash播放器并没有内建带宽检测系统,要想测出用户带宽,需要通过Flash播放器下载一个文件(如JPEG文件),通过下载的大小和所花的时间可以计算出平均下载速度,根据8个比特等于1个字节,1000个字节等于1个kilobyte(kb),转换公式为:

kilobits(KB) = bytes /1000 * 8;

package {
 import flash.display.Sprite;
 import flash.events.Event;
 public class Sample0625 extends Sprite
 {
  public function Sample0625()
  {
   var bandwidthTester:BandwidthTest = new BandwidthTest( );
   bandwidthTester.addEventListener(Event.COMPLETE, onBandwidthTest);
   bandwidthTester.test( );
  }
  
  private function onBandwidthTest(event:Event):void
  {
   trace(event.target.detectedBandwidth);
  }
 }
}
import flash.events.EventDispatcher
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.utils.getTimer;
internal class BandwidthTest extends EventDispatcher
{
 private var _downloadCount:uint;
 private var _bandwidthTests:Array;
 private var _detectedBandwidth:Number;
 private var _startTime:uint;
 
 public function BandwidthTest()
 {
  _downloadCount = 0;
  _bandwidthTests = new Array( );
 }
 
 public function get detectedBandwidth( ):Number 
 {
  return _detectedBandwidth;
 }
 
 // Run the bandwidth test. 
 public function test( ):void 
 {
  // Use a URLLoader to load the data. 
  var loader:URLLoader = new URLLoader( );
  // Use a URL with a unique query string to ensure the data  is 
  // loaded from the server and not from browser cache. 
  var request:URLRequest = new URLRequest("Test.jpg?unique=" + (new Date( )).getTime( ));
  loader.load(request);
  loader.addEventListener(Event.OPEN, onStart);
  loader.addEventListener(Event.COMPLETE, onLoad);
 }
 
 // When the file starts to download get the current timer value.
 private function onStart(event:Event):void 
 {
  _startTime = getTimer( );
 }
 
 private function onLoad(event:Event):void 
 {
  // The download time  is  the timer value when the file has downloaded 
  // minus the timer value when the value started downloading. Then 
  // divide by 1000 to convert from milliseconds to seconds. 
  var downloadTime:Number = (getTimer( ) - _startTime) / 1000;
  _downloadCount++;
  // Convert from bytes to kilobits. 
  var kilobits:Number = event.target.bytesTotal / 1000 * 8;
  // Divide the kilobits by the download time.
  var kbps:Number = kilobits / downloadTime;
  // Add the test value to the array. 
  _bandwidthTests.push(kbps);
  if(_downloadCount == 1) 
  {
   // If it's only run one test then run the second. 
   test( );
  }
  else if(_downloadCount == 2) 
  {
   // If it's run two tests then determine the margin between the 
   // first two tests. 
   // If the margin  is  small ( in  this example, less than 50 kbps) 
   // then dispatch a complete event. If not run a test. 
   if(Math.abs(_bandwidthTests[0] - _bandwidthTests[1]) < 50) 
   {
    dispatchCompleteEvent( );
   }
   else 
   {
    test( );
   }
  }
  else 
  {
   // Following the third test dispatch a complete event. 
   dispatchCompleteEvent( );
  }
 }
 
 private function dispatchCompleteEvent( ):void 
 {
  // Determine the avarage bandwidth detection value. 
  _detectedBandwidth = 0;
  var i:uint;
  for(i = 0; i < _bandwidthTests.length; i++) 
  {
   _detectedBandwidth += _bandwidthTests[i];
  }
  _detectedBandwidth /= _downloadCount;
  // Dispatch a complete event. 
  dispatchEvent(new Event(Event.COMPLETE));
 }
}

3. 使用SharedObject存储信息

ActionScript中,SharedObject类实现了客户端机器数据的持久性存储。有两种类型的共享对象:本地和远程

本地 -- Local Shared Objects(LSOs)

远程 -- Remote Shared Objects(RSOs)

Flash的LSOs就如同Web浏览器中的cookies,它们被一些开发者称为"超级cookies",因为LSOs可以存储大量数据,且存储和读取的都是原生的ActionScript数据类型

LSOs默认的空间大小100KB,用户可以通过Flash Player's Settings Manager控制LSOs的使用空间大小。存储在客户端的LSO文件是一种二进制文件,扩展名为.sol,同一个域的Flash电影通过flash.net.SharedObject类读写.sol文件

当.sol文件创建后,被放置在Flash播放器对应的应用程序数据目录

Windows XP:
For Web sites -- C:\Documents and Settings\<user>\Application Data\Macromedia\Flash Player
\#SharedObjects\<random code>\<domain>\<path>\<object name>.sol For AIR Applications -- C:\Documents and Settings\<user>\Application Data\<AIR Application Reverse Domain Name>
\Local Store\#SharedObjects\<flash filename>.swf\<object name>.sol Windows Vista/2008: C:/Users/username/<user>/AppData/Roaming/Macromedia/Flash Player/#SharedObjects/<domain>/<path>
/<flash filename>.swf/<object name>.sol

SharedObject类的静态方法getLoal()用于创建或打开共享对象,它至少需要一个参数指明共享对象名称:

var example:SharedObject = SharedObject.getLocal("myOption");

getLocal()方法首先试图定位找到LSO,如果找不到则根据这个名字创建新的,否则就返回SharedObject实例

SharedObjects对象有个内建的属性data,data属性类型为object,因此可以添加任何信息(不能存储可视化对象,如Sprite,TextFields)

package {
 import flash.display.Sprite;
 import flash.net.SharedObject;
 public class Sample0625 extends Sprite
 {
  public function Sample0625()
  {
   var shareObj:SharedObject = SharedObject.getLocal("myOption");
   shareObj.data.name = "hxw";
   shareObj.data.gameList = new Array("wow","war3","dota");
   shareObj.data.loginTime = new Date();
   shareObj.data.newObj = {age:"23",city:"shenzhen",msn:null};
  }
 }
}

4. 保存SharedObject对象(Flush)

以下几种情况会导致Flash自动试图保存LSO数据到硬盘上:

* 当Flash播放器关闭时

* 当SharedObject对象被垃圾回收时

* 当调用SharedObject.clear()、SharedObject.close()方法时

如果需要立即保存共享对象数据,我们可以显式调用SharedObject.flush()方法:

var flushResult:String = sharedObject.flush(minDiskSpace)

参数minDiskSpace为必须分配给此对象的最小磁盘空间,单位为字节,默认为0

当flush()方法触发时,它试图把数据写到客户端上,调用结果有三种(flushResult的返回值):

SharedObjectFlushStatus.FLUSHED -- 成功保存

SharedObjectFlushStatus.PENDING -- 显示对话框,要求用户增加磁盘空间量以供此域中的对象使用

抛出Error -- 用户拒绝存储或Flash播放器因某种原因导致存储失败

PS: 为了避免返回PENDING,请为minDiskSpace传递一个值

package {
 import flash.display.Sprite;
 import flash.events.NetStatusEvent;
 import flash.net.SharedObject;
 import flash.net.SharedObjectFlushStatus;
 public class Sample0625 extends Sprite
 {
  private var example:SharedObject;
  
  public function Sample0625()
  {
   example = SharedObject.getLocal("example");
   example.data.someData = "a value";
   
   var flushResult:String = "";
   
   try 
   {
    flushResult = example.flush( );
    if ( flushResult == SharedObjectFlushStatus.PENDING ) 
    {
     //当用户做出选择后,netStatus事件被激活,需要定义一个事件处理函数,当事
     //件处理函数被触发时,传递进一个类型为flash.events.NetStatusEvent的事件,
     //检查info.code属性值判断用户是同意(SharedObject.Flush.Success)
//还是拒绝(SharedObject.Flush.Failed) example.addEventListener( NetStatusEvent.NET_STATUS, onStatus ); } else if ( flushResult == SharedObjectFlushStatus.FLUSHED ) { //存储成功 } } catch ( e:Error ) { //这里代表用户的本地存储设置为'Never',可以在这里弹出一个设置框让用户修改 //Security.showSettings( SecurityPanel.LOCAL_STORAGE ); } finally { trace(example.data.someData); trace(flushResult); } } private function onStatus(event:NetStatusEvent):void { if (event.info.code == "SharedObject.Flush.Success" ) { //用户选择了同意 } else if (event.info.code == "SharedObject.Flush.Failed" ) { //用户选择了拒绝 } //只需要监听一次,所以移除掉该事件监听 example.removeEventListener( NetStatusEvent.NET_STATUS, onStatus ); } } }

5. 删除SharedObject里保存的数据

用delete删除data集合中的某个属性,或使用clear()方法清除整个共享对象(即删除了.sol文件)

package {
 import flash.display.Sprite;
 import flash.net.SharedObject;
 public class Sample0626 extends Sprite
 {
  public function Sample0626()
  {
   var obj:SharedObject = SharedObject.getLocal("jay");
   obj.data.name = "hxw";
   obj.data.pwd = "millfox";
   obj.data.game = "wow";
   
   for(var str1:String  in  obj.data)
   {
    trace(str1 + ":" + obj.data[str1]);
   }
   
   delete obj.data.pwd;
   trace("----------------------");
   
   for(var str2:String  in  obj.data)
   {
    trace(str2 + ":" + obj.data[str2]);
   }
   
   obj.clear();
   trace("----------------------");
   
   for(var str3:String  in  obj.data)
   {
    trace(str3 + ":" + obj.data[str3]);
   }
  }
 }
}
将会输出:
name:hxw
game:wow
pwd:millfox
----------------------
name:hxw
game:wow
----------------------

6. 使用SharedObject存储自定义类实例

LSOs使用特殊的二进制格式,Action Message Format(AMF),当要在LSO中存储类实例时,实例会被编码为包含属性的普通的object。这样当重新从共享对象中读取实例时,已经不是原来的类实例了,因为已不能根据类型信息解码回来

解决方法是调用flash.net.registerClassAlias("classAliasName",ClassName)

package {
 import flash.display.Sprite;
 import flash.net.SharedObject;
 import flash.net.registerClassAlias;
 public class Sample0703 extends Sprite
 {
  public function Sample0703()
  {
   registerClassAlias("hxw.class.person",Person);
   
   var shareObj:SharedObject = SharedObject.getLocal("userInfo");
   
   if(shareObj.data.person == undefined)
   {
    var obj:Person = new Person("胡晓伟",27);
    shareObj.data.person = obj;
   }
   else
   {
    delete shareObj.data.person;
   }
   
   trace(shareObj.data.person  is  Person);
   //trace(shareObj.data.person.toString()); 
  }
 }
}
internal class Person
{
 private var _name:String;
 private var _age:int;
 
 public function Person(name:String,age:int)
 {
  _name = name;
  _age = age;
 }
 
 public function toString():String
 {
  return _name + "  is  " + _age + " years old";
 }
}

7. swf文件之间共享LSO数据

默认情况下,LSOs存储的名称是唯一的,这主要是为了防止名称冲突(不同swf生成的sol文件,会在以这个swf命名的文件夹下)

如果要让同一个域中的多个swf文件能访问同一个LSO,可以指定SharedObject.getLocal("example","/")的第二个参数

package {
 import flash.display.Sprite;
 import flash.events.MouseEvent;
 import flash.net.SharedObject;
 import flash.text.TextField;
 public class Sample0703 extends Sprite
 {
  private var shareObj:SharedObject;
  private var textBox:TextField;
  
  public function Sample0703()
  {
   shareObj = SharedObject.getLocal("clickRate","/");
   
   if(shareObj.data.clickNumber == undefined)
   {
    shareObj.data.clickNumber = 0;
   }
   
   textBox = new TextField();
   this.addChild(textBox);
   stage.addEventListener(MouseEvent.CLICK,onClick);
  }
  
  
  
  private function onClick(event:MouseEvent):void
  { 
   shareObj.data.clickNumber += 1;
   textBox.text = shareObj.data.clickNumber;
  }
 }
}

8. 让用户设置LSO的空间大小

使用Security.showSettings(SecurityPanel.LOCAL_STORAGE)弹出对话框,让用户自定义大小

9. 同一台电脑的多个swf文件通信(LocalConnection)

分为发送端(Send)和接收端(Receive)

发送端LocalConnection.send("_myChannel", 'receiveMethod');

接收端LocalConnection.connect("_myChannel");

若不想在send()方法中指定域名,但要向Flash Player指出接收方和发送方LocalConnection对象不在同一个域中,可在connect()和send()调用中的连接名之前加一个下划线"_",这样Flash Player不会加入域信息,如果不是以下划线开头,则通信信道名称字符串将被自动转换成domain:connectionName,而不管是本地域还是远程域

同一个域

// receivingLC  is  in  http://www.domain.com/receiving.swf
receivingLC.connect('myConnection');
// sendingLC  is  in  http://www.domain.com/sending.swf
// myMethod()  is  defined  in  sending.swf
sendingLC.send('myConnection', 'myMethod');

具有可预知域名的不同域

// receivingLC  is in  http://www.domain.com/receiving.swf
receivingLC.allowDomain('www.anotherdomain.com');
receivingLC.connect('myConnection');
// sendingLC  is  in http://www.anotherdomain.com/sending.swf 
sendingLC.send('www.domain.com:myConnection', 'myMethod');

具有不可预知域名的不同域

// receivingLC  is  in  http://www.domain.com/receiving.swf
receivingLC.allowDomain('*');
receivingLC.connect('_myConnection');
// sendingLC  is  in  http://www.anotherdomain.com/sending.swf 
sendingLC.send('_myConnection', 'myMethod');

发送端代码:

package {
 import flash.display.Sprite;
 import flash.events.MouseEvent;
 import flash.events.StatusEvent;
 import flash.net.LocalConnection;
 public class MySender extends Sprite
 {
  public function MySender()
  {
   stage.addEventListener(MouseEvent.CLICK,onClick);
  }
  
  private function onClick(event:MouseEvent):void
  {
   var localConn:LocalConnection = new LocalConnection();
   localConn.send("_myChannel","showGame","World Of Warcraft");
   localConn.addEventListener(StatusEvent.STATUS,onStatus);
  }
  
  private function onStatus(event:StatusEvent):void
  {
   trace(event.level);
  }
 }
}

接收端代码

package {
 import flash.display.Sprite;
 import flash.events.MouseEvent;
 import flash.net.LocalConnection;
 import flash.text.TextField;
 public class MyReceiver extends Sprite
 {
  private var textBox:TextField;
  private var localConn:LocalConnection;
  
  public function MyReceiver()
  {
   textBox = new TextField();
   this.addChild(textBox);
   
   stage.addEventListener(MouseEvent.CLICK,onClick);
  }
  
  private function onClick(event:MouseEvent):void
  {
   localConn = new LocalConnection();
   localConn.allowDomain("*");
   localConn.connect("_myChannel");
   localConn.client = this;
  }
  
  public function showGame(str:String):void
  {
   textBox.text = str;
  }
 }
}

PS: 还有个与allowDomain( )类似的方法allowInsecureDomain( )方法,大多数情况下这两种方法是一样,不同点在于HTTPS的使用上,当flash来自于HTTPS,其里面的本地连接实例不能和来自于HTTP的flash通信,除非使用allowInsecureDomain( ),默认下HTTP 和HTTPS 的flash是不能通信的,即使是在同一个域。并不推荐使用allowInsecureDomain( ),这样可能会带来不安全因素

10. Loader与URLLoader的区别

Loader -- 读取swf、图片(jpg、png、gif)

URLLoader -- 文本文件(xml、php、jsp...)

Loader加载过来的数据类型:

如果加载图片文件(jpg,gif,png等)时,Loader.content得到数据类型是Bitmap对象;

如果加载SWF文件(flash 9 版本)时,Loader.content得到数据类型是MovieClip对象;

如果加载SWF文件(flash 9 以前版本) 时, Loader.content得到数据类型是AVM1Movie对象;

Loader是给它的contentLoaderInfo属性增加事件,而不是给Loader对象增加事件:

loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);

URLLoader是给它自己增加事件:

xmlLoader.dataFormat=URLLoaderDataFormat.TEXT;

xmlLoader.addEventListener(Event.COMPLETE,xmlLoaded);

posted @ 2010-07-15 15:23  CoderWayne  阅读(1267)  评论(0编辑  收藏  举报