Flash 9 中如何使用 Loader 加载
2008年2月12日, 17:24
做一个 Flash 程序,要实现一个 loading 过程,当加载一个比较大的外部资源,要显示加载进度,当外部资源全部都加载到本地播放器(Flash Player)以后,就开始播放。
下面是装载的完整过程:(以源码中的文件为例)
1)Player 装载 LoaderTest.swf,并产生相应的 LoaderInfo (可以通过在 LoaderTest 中访问 this.loaderInfo 属性得到)
2)LoaderTest 中使用 flash.display.Loader 对象调用 load 方法进行装载,装载的过程中会产生 open / progress / init / complete 几个事件,如果发生读取错误,会产生 ioError 事件
3)loader 装载完成以后,可以使用 loader.content 来访问被加载的影片(SimpleMovie.swf),使用 loader.contentLoaderInfo 来访问 SimpleMovie.swf 的 LoaderInfo 类的实例对象(即:这个时候在 SimpleMovie 里面访问到的 loaderInfo 属性与 LoaderTest.loader.contentLoaderInfo 是同样一个对象)
装载完成以后整个关系图可以如下表示:(图片来自 Adobe Flex Laugnage Reference)

在实际使用 loader 的过程中遇到了一个小小的问题:装载比较大的 swf 时,往往没有完全装载成功,影片剪辑就开始播放了。
要看到这个效果需要在 IDE 中编译执行 LoaderTest.fla,在 Test Movie(快捷键 Ctrl + Enter)打开的 Flash Player 中从 View 菜单选择 Download Settings,设置一个比较慢的下载速度,比如 56K(4.7KB/S),然后再从 View 菜单中选一次 Simulate Download(快捷键还是 Ctrl + Enter),这样,我们看到的效果是,进度条到了 100% 以后就立马跳出来的是 SimpleMovie 里面的 Over! 画面了。从 Flash IDE 的输出我们看到这样的执行顺序:Open -> Progress -> Init -> Complete (在我的机器上,Init 大概是发生在 Progress 到了 8% 左右的时候)。
既然原因找到了,要解决这个问题的办法也很简单,修改 movieInit 这个方法,将 movieHolder.stop(); 前面的注释去掉
- protected function movieInit(event:Event):void {
- trace("init");
- movieHolder = MovieClip(loader.content);
- //设定当前 fps 同被加载进来的 .swf 相同
- stage.frameRate = loader.contentLoaderInfo.frameRate;
- //看看取消注释后有什么变化
- //movieHolder.stop();
- }
再重新编译执行一下,就可以看到正确的效果了。
仔细看了一下 Adobe 的参考文档,里面对 Loader 的 init 事件说明大概是这样的:(翻译自 LoaderInfo 参考手册)
当被加载对象的所有属性和方法都能被访问到的时候,就产生该事件。要产生这个事件必须同时满足下列两种情况:
1)被加载的 DisplayObject 对象(本代码中的 SimpleMovie.swf,对于 LoaderTest 来说就是 loader.content)的所有属性都能被访问
且这个 DisplayObject 关联的一个叫做 loaderInfo 对应的 LoaderInfo 对象能被访问到(我的理解,能被访问到就是不为空)
2)这个 DisplayObject 里面所有子对象都被构造好、准备就绪了
也就是说,当 LoaderTest 中的 loader.contentLoaderInfo 和 loader 的其它的一些属性能被访问了,这个 contentLoaderInfo 就迫不及待的发出了 init 的信号,而此时,装载的过程并没有真正完成,还有很大一部分内容都没有被加载呢。真正加载完成、一个字节都没有漏掉的时候应该是 complete 这个事件发生的时候,只有在这个时候,被 loader 装载的 swf 之中每个对象、每个属性才能被真正访问到。
如果,我们把 stage.addChild(movieHolder) 这句从 loadComplete 移到 movieInit 里面来,我们可以看到 Flash 的边装载边播放的特性。即在 init 发生以后, SimpleMovie 就开始从第一帧开始播放了,此时的 Progress 大概在 8% 左右。
不过,一般情况下不要利用这个特性这么做。因为,在项目实践中,Tiger 发现被事先装载的部分可能是音乐,这样会出现音乐先播放,而画面跟不上的情况。
写这篇之前当然进行了一些搜索工作,找到一些文章说明 Flash 9 以前版本的 Loader 搞反了 init 和 complete 这两个事件,有兴趣可以读一下。
参考阅读:
1)http://www.awflasher.com/blog/archives/468
2)http://whatdoiknow.org/archives/001982.shtml
