如何扩展 Loader 类并返回 ActionScript / Flex 3 中的缓存资源?

发布于 2024-08-01 18:09:52 字数 2386 浏览 7 评论 0原文

我一直在尝试创建一个通用资产加载器类(在 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: Error #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 之外的其他内容?

I've been trying to create an universal asset loader class (with help of the folks here at stackoverflow), which remembers previousely downloaded assets by storing them in an associative array.

This is the end result:

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 equals "http://site.com/assets/"

Now, my problem is that it is causing the client to crash whenever it tries to retrieve the caches version (the newly downloaded one does work) from the class:

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
}

When the cached version is being loaded, I get the following error in dutch: "TypeError: Error #1034: Afgedwongen typeomzetting is mislukt: kan flash.display::MovieClip@5c13421 niet omzetten in flash.display.Bitmap. at GameShip/onShipAssetComplete()" - means something like "type convertion has failed, can not convert flash.display::MovieClip@... to flash.display.Bitmap".

So, I wonder, how should I extend this loader class and make it return a cached asset the right way? Is my way of storing the asset in the array invalid maybe? Or should I use something else than loadBytes in the AssetLoader method?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

从﹋此江山别 2024-08-08 18:09:52

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

这是我的意思的一个例子。 看一下一个退化的情况...这是一个可以缓存的请求,但不是因为 laoder 正在加载...

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;
    }
}
}

I'm not sure why you are insistent on using the contentLoaderInfo if you are busy encapsulating the functionality -- go ahead and encapsulate the data too. Also, why store the bytes for an object instead of a simple reference to the actual object?

Here is an example of what I mean. Take a look at the one degenerate case ... that is a request that could be cached but isn't because the laoder is in the process of loading ...

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();
    }
}
}

The changed up asset Loader:

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));
        }
    }
}

And the event:

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;
    }
}
}
窝囊感情。 2024-08-08 18:09:52

您可能知道这一点,但是有一个 as3 的开源库(bulkloader) 不仅可以做到这一点,而且还可以做更多的事情。 (这里无耻的插件,因为我是作者。

至少,阅读源代码可能会给你关于要解决的问题的想法,也许还有一些实现指针。

干杯
亚瑟·德伯特

You are probably aware of that, but there is an open source library for as3 (bulkloader) that does that and much more. (shameless plug here, since I am the author.

At the very least, reading through the source code might give you ideas on issues to tackle and maybe some implementation pointers.

Cheers
Arthur Debert

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文