加载进度 = 已加载量 / 加载总量
因为是并行(多个Loader同时)加载,所以: 加载进度 = 各个Loader已加载量的总和 / 各个Loader加载总量之和
如何能一下子汇总全部Loader的“已加载量 / 加载总量”这两种数据呢?
假设有LoaderA、LoaderB 2个加载器,它们同时加载不同的swf资源。
在某个时点:
各个Loader已加载量的总和 = LoaderA.loaderInfo.bytesLoaded + LoaderB.loaderInfo.bytesLoaded
各个Loader加载总量之和 = LoaderA.loaderInfo.bytesTotal + LoaderB.loaderInfo.bytesTotal
于是该时点并行加载的进度可以计算出来了。
Flex框架通过设置定时器,来定时计算并行加载进度。
另外,RSL是顺序下载的(http://blog.csdn.net/tiangej/article/details/7353860),也就是说一个Loader加载完毕后,下一个Loader才开始下载,也就是说在上一个Loader没有加载完毕之前,下一个Loader中的bytesLoaded和bytesTotal的值都是0。
因此,“各个Loader加载总量之和”是不能在加载之初就能确定的,getByteValues()函数的每一次被调用,计算出的“各个Loader加载总量之和 ”都可能发生变化。
这也解释了如下现象:
Flex进度条的进度突然退后了。
>>源代码参考:
mx.preloaders.Preloader.as
public function initialize(showDisplay:Boolean,
displayClassName:Class,
backgroundColor:uint,
backgroundAlpha:Number,
backgroundImage:Object,
backgroundSize:String,
displayWidth:Number,
displayHeight:Number,
libs:Array = null,
sizes:Array = null,
rslList:Array = null,
resourceModuleURLs:Array = null,
applicationDomain:ApplicationDomain = null):void
{
......
// 定时器
timer = new Timer(10);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
......
}
private function timerHandler(event:TimerEvent):void
{
// loaded swfs may not have root right away
if (!root)
return;
//获得并行加载进度数据
var bytes:Object = getByteValues();
var loaded:int = bytes.loaded;
var total:int = bytes.total;
//将进度数据通过事件发送给事件监听器,以此来更新画面上显示的进度条状态
// Dispatch a progress event (later we might conditionalize this
// so that it isn't sent on a cache load).
dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS,
false, false, loaded, total));
if (waitingToLoadResourceModules)
{
if (applicationDomain.hasDefinition("mx.resources::ResourceManager"))
{
waitingToLoadResourceModules = false;
rslListLoader = resourceModuleListLoader;
rslDone = false;
// Start loading the resourceModules
rslListLoader.load(rslProgressHandler,
rslCompleteHandler,
rslErrorHandler,
rslErrorHandler,
rslErrorHandler);
}
}
private function getByteValues():Object
{ //获取主swf的加载器,它由FlashPlayer提供
var li:LoaderInfo = root.loaderInfo;
var loaded:int = li.bytesLoaded;
var total:int = li.bytesTotal;
//循环多个RSL加载器,累加下载数据
// Look up the rsl bytes and include those
var n:int = rslListLoader ? rslListLoader.getItemCount() : 0;
for (var i:int = 0; i < n; i++)
{
loaded += rslListLoader.getItem(i).loaded;
// If the rsl total is zero then provide an average rsl size
// to set rough expectations.
var rslTotal:int = rslListLoader.getItem(i).total;
total += rslTotal;
}
return { loaded: loaded, total: total };
}