如何在actionscript / flex 3中扩展Loader类并返回缓存的资产?

时间:2009-08-15 13:50:46

标签: actionscript-3 caching flex3 asset-management

我一直在尝试创建一个通用资产加载器类(在stackoverflow的帮助下),它通过将它们存储在关联数组中来记住先前下载的资产。

这是最终结果:

AssetLoader.as

package
{
    import flash.display.Loader;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.utils.ByteArray;

    public final class AssetLoader extends Loader
    {
        public static var storedAssets:Object = {};
        private var postUrl:String;
        private var urlRequest:URLRequest;
        private var cached:Boolean = false;

        public final function AssetLoader(postUrl:String):void
        {
            this.postUrl = postUrl;
            if (storedAssets[postUrl])
            {
                cached = true;
            }
            else
            {
                urlRequest = new URLRequest(Settings.ASSETS_PRE_URL + postUrl);
                contentLoaderInfo.addEventListener(Event.COMPLETE, OnAssetLoadComplete);
            }
        }

        //starts loading the asset
        public final function loadAsset():void
        {
            if (cached)
            {
                loadBytes(storedAssets[postUrl]);
            }
            else
            {
                load(urlRequest);
            }
        }

        //runs when the asset download has been completed
        private final function OnAssetLoadComplete(event:Event):void
        {
            storedAssets[postUrl] = contentLoaderInfo.bytes;
        }
    }
}

Settings.ASSETS_PRE_URL等于“http://site.com/assets/

现在,我的问题是,当它尝试从类中检索缓存版本(新下载的版本确实有效)时,它会导致客户端崩溃:

var assetLdr:AssetLoader = new AssetLoader("ships/" + graphicId + ".gif");
assetLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, onShipAssetComplete);
assetLdr.loadAsset();

private function onShipAssetComplete(event:Event):void
{
    var shipImage:Bitmap = Bitmap(event.target.loader.content);
    // Do stuff with shipImage
}

当加载缓存版本时,我在荷兰语中收到以下错误:“TypeError:错误#1034:Afgedwongen typeomzetting is mislukt:kan flash.display :: MovieClip @ 5c13421 niet omzetten in flash.display.Bitmap。at GameShip / onShipAssetComplete()“ - 表示”类型转换失败,无法将flash.display :: MovieClip @ ...转换为flash.display.Bitmap“。

所以,我想知道,我应该如何扩展这个加载器类并让它以正确的方式返回缓存资产?我在数组中存储资产的方式可能无效吗?或者我应该在AssetLoader方法中使用除了loadBytes之外的其他内容吗?

2 个答案:

答案 0 :(得分:3)

如果您忙于封装功能,我不确定为什么您坚持使用contentLoaderInfo - 继续并封装数据。另外,为什么要存储对象的字节而不是对实际对象的简单引用?

这是我的意思的一个例子。看看一个退化的情况......这是一个可以缓存的请求,但不是因为负载正处于加载过程中......

package 
{

import flash.display.BitmapData;
import flash.display.Sprite;

public class TestAssetLoader extends Sprite
{
    public var loader:AssetLoader;
    public var degenerateLoader:AssetLoader;
    public var cachedLoader:AssetLoader;

    public function TestAssetLoader()
    {
        loader = new AssetLoader("picasso_blue_guitar.jpg");
        loader.addEventListener(AssetLoaderEvent.ASSET_LOAD_COMPLETE, handleAssetLoaded);
        loader.loadAsset();

        // NOTE: you'll have to think about this case ....
        // where an asset is in the process of loading when you get another request
        // e.g. it isn't yet cached but is already being loaded ... 
        degenerateLoader = new AssetLoader("picasso_blue_guitar.jpg");
        degenerateLoader.loadAsset();
    }

    private function handleAssetLoaded(event:AssetLoaderEvent):void
    {
        // here is your content
        // var myImage:Bitmap = Bitmap(event.content);

        // This is guaranteed to hit the cache
        cachedLoader = new AssetLoader("picasso_blue_guitar.jpg");
        cachedLoader.loadAsset();
    }
}
}

已更改的资产加载程序:

package
{
    import flash.display.Loader;
    import flash.events.Event;
    import flash.net.URLRequest;

    public final class AssetLoader extends Loader
    {
        public static var ASSETS_PRE_URL:String = "";

        public static var storedAssets:Object = {};
        private var postUrl:String;

        public final function AssetLoader(_postUrl:String):void
        {
                postUrl = _postUrl;
        }

        //starts loading the asset
        public final function loadAsset():void
        {
            if(storedAssets[postUrl])
            {
                trace("cached load");

                var resource:DisplayObject = storedAssets[postUrl];

                if(resource is Bitmap)
                {
                    resource = new Bitmap(Bitmap(resource).bitmapData);
                }

                dispatchEvent(new AssetLoaderEvent(AssetLoaderEvent.ASSET_LOAD_COMPLETE, resource));
            }
            else
            {
                var urlRequest:URLRequest = new URLRequest(ASSETS_PRE_URL + postUrl);
             contentLoaderInfo.addEventListener(Event.COMPLETE, OnAssetLoadComplete);
                 load(urlRequest);
            }
        }

        //runs when the asset download has been completed
        private final function OnAssetLoadComplete(event:Event):void
        {
            trace("non-cached load");
            var loader:Loader = Loader(event.target.loader); 
            storedAssets[postUrl] = loader.content;
            dispatchEvent(new AssetLoaderEvent(AssetLoaderEvent.ASSET_LOAD_COMPLETE, loader.content));
        }
    }
}

事件:

package
{
import flash.display.DisplayObject;
import flash.events.Event;

public class AssetLoaderEvent extends Event
{
    public static const ASSET_LOAD_COMPLETE:String = "AssetLoaderEvent_LoadComplete";

    public var  content:DisplayObject;

    public function AssetLoaderEvent(type:String, _content:DisplayObject, bubbles:Boolean=false, cancelable:Boolean=false)
    {
        content = _content; 
        super(type, bubbles, cancelable);
    }

    override public function clone():Event
    {
        return new AssetLoaderEvent(type, content, bubbles, cancelable); 
    }

    override public function toString():String
    {
        return "[AssettLoaderEvent] " + type;
    }
}
}

答案 1 :(得分:1)

您可能已经意识到这一点,但是有一个as3(bulkloader)的开源库可以做到这一点以及更多。 (这里是无耻的插件,因为我是作者。

至少,阅读源代码可能会为您提供解决问题的想法,也许还有一些实现指针。

干杯 亚瑟·德伯特