【问题标题】:Howto extend Loader class and return cached assets in actionscript / flex 3?如何在 actionscript / flex 3 中扩展 Loader 类并返回缓存的资产?
【发布时间】:2009-08-15 13:50:46
【问题描述】:

我一直在尝试创建一个通用资产加载器类(在 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 以外的其他东西?

【问题讨论】:

  • 你看过 Eli Greenfield 的 SuperImage 吗?缓存位非常好:quietlyscheming.com/blog/2007/01/23/…
  • 我刚刚检查过了。但是,它仅适用于图像,而我的课程适用于所有资产类型。另外,我想知道我发布的代码有什么问题。

标签: actionscript-3 caching flex3 asset-management


【解决方案1】:

如果您正忙于封装功能,我不确定您为什么坚持使用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;
    }
}
}

【讨论】:

  • 非常感谢,您试过了吗?我刚刚在我的代码中实现了它,第一个图像加载正常(下载),几秒钟后我调用第二个图像(缓存),它显示正常。但是,当第二个(缓存的)图像加载时,第一个图像突然消失了。知道是什么原因造成的吗?
  • 是的 - 我的错。我已更新代码以在获取缓存副本时复制位图资源。您不能将相同的 DisplayObject 添加到具有两个不同父级的舞台。您可能希望将 bitmapData 存储在地图中而不是 Bitmap ...这取决于您。
  • 谢谢。所以我想我必须对声音等做同样的事情?
  • 我不确定声音 - 肯定是添加到显示列表中的任何内容。
【解决方案2】:

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

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

干杯 亚瑟·德伯特

【讨论】:

  • 干得好!我没有使用它,因为我认为它仅用于图像,这里可能是错误的。它似乎确实有太多我想要的功能,这会导致不需要的代码量。
  • 它加载任何东西。它是 16kb 编译的,如果太大了,去掉你不需要的加载类型和方便的方法(getNetStream、getSound 等),你应该很高兴。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多