• (转载)Flash Loader加载完成不发送COMPLETE和ERROR事件的问题分析


    (转载)http://blog.dou.li/flash-loader%E5%8A%A0%E8%BD%BD%E5%AE%8C%E6%88%90%E4%B8%8D%E5%8F%91%E9%80%81complete%E5%92%8Cerror%E4%BA%8B%E4%BB%B6%E7%9A%84%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90.html

    Flash进行资源加载时常会“停住”,表现为加载进度卡在某个地方。跟踪发现Loader的progress为100%,但未发送Event.COMPLETE或IOErrorEvent.IO_ERROR等事件。

    目前项目加载底层的队列依赖于Loader(URLLoader)的COMPLETE和ERROR事件,如果这两个事件不发送将导整套加载机制崩溃 – -,后续跟踪发现的确会如此。

    问题展示

    以下给出一个Demo,可重现Loader加载到100%但不会发送Event.COMPLETE或IOErrorEvent.IO_ERROR等事件的问题:

    package
    {
        import flash.display.Loader;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.HTTPStatusEvent;
        import flash.events.IOErrorEvent;
        import flash.events.ProgressEvent;
        import flash.net.URLRequest;
     
        public class CheckFailSWFLoad extends Sprite
        {
            public function CheckFailSWFLoad()
            {
                var load:Loader = new Loader();
                load.contentLoaderInfo.addEventListener(Event.COMPLETE, onEvent);
                load.contentLoaderInfo.addEventListener(Event.INIT, onEvent);
                load.contentLoaderInfo.addEventListener(Event.OPEN, onEvent);
                load.contentLoaderInfo.addEventListener(Event.UNLOAD, onEvent);
                load.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, onEvent);
                load.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onEvent);
                load.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
     
                load.load(new URLRequest("a.swf"));
            }
     
            private function onEvent(e:Event):void
            {
                trace(e.type);
            }
     
            private function onProgress(e:ProgressEvent):void
            {
                trace(e.type + ":" + e.bytesLoaded + "/" + e.bytesTotal);
            }
        }
    }
    执行结果:
    open
    progress:0/524216
    progress:8192/524216
    progress:16384/524216
    progress:24576/524216
    
    这里省略若干条……
    progress:507904/524216
    progress:516096/524216
    progress:524216/524216

    如上,对Loader的所有网络相关事件进行监听,只有Event.OPEN和ProgressEvent.PROGRESS事件有响应,progress达100%时无后续输出。

    附上一个正常的加载输出:
    
    open
    progress:0/75744
    progress:8192/75744
    progress:16384/75744
    progress:24576/75744
    progress:32768/75744
    progress:40960/75744
    progress:49152/75744
    progress:57344/75744
    progress:65536/75744
    progress:73728/75744
    progress:75744/75744
    init
    httpStatus
    complete

    正常的加载最终会抛出Event.COMPLETE事件的。

    原因分析

    这所以导致面结果是因为,a.swf文件是一个已损坏的文件,要么与原文件大小不等、要么大小一到致但数据错误,都会导致以上问题。有兴趣可以拿个.swf文件改一下内容试试。

    如果工程运行在浏览器中,由于浏览器的Cache,一次加载失败后会在Cache中留下损坏的文件。此时,就算是刷新再进,浏览器不会从Server端获取文件,将继续得到Cache中的坏数据。

    用URLLoader有没有问题呢?

    我们用的Loader作测试,经试验用URLLoader无问题,因为URLLoader只关注文件本身,照原样将文件下载下来(把URLLoader.dataFormat 设为URLLoaderDataFormat.BINARY)。而Loader是显示对象,除加载外还会将加载的数据转为DisplayObject,以至其加载不再纯粹。

    但对于加载一个swf最终作为DisplayObject可有两种方案:

    1. 用Loader加载后使用;
    2. 用URLLoader加载得到ByteArray,再用Loader加载ByteArray得到DisplayObject;

    两种方案在Loader这一步都会出现这个问题。

    加载损坏的图像有没有问题呢?

    经试验,加载一张损坏的图片,Loader能正常发送Error事件。

    解决方案

    private function onProgress(e:ProgressEvent):void
    {
        if(e.bytesTotal != realSize)
            reload();
    }

    记录需要加载的资源真实大小,加载时判断加载的bytesTotal是否与记录的大小一致,不一致则判定文件已损坏,发起重载。

    对于上面说的浏览器Cache问题,解决方案有3:

    1. 引导用户手动去清浏览器Cache;
    2. 重载时让你的URL发生改变,加个可变参数,如:http://domain/a.swf?v=143,这个143在重载时换一个值;
    3. 摈弃浏览器Cache,自己用SharedObject构建Cache,加载URL全用随机参数(v的值每次改变),发现坏数据清掉SharedObject对应数据就行;

    转载请注明:兜·里 » Flash Loader加载完成不发送COMPLETE和ERROR事件的问题分析

  • 相关阅读:
    1015. 德才论
    1014. 福尔摩斯的约会
    1013. 数素数
    1012. 数字分类
    1011. A+B和C
    1010. 一元多项式求导
    1009. 说反话
    1008. 数组元素循环右移问题
    1007. 素数对猜想
    1006. 换个格式输出整数
  • 原文地址:https://www.cnblogs.com/Robotke1/p/3312934.html
Copyright © 2020-2023  润新知