文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>silverlight游戏设计(二)资源管理篇(下)--资源的状态通知、管理与缓存

silverlight游戏设计(二)资源管理篇(下)--资源的状态通知、管理与缓存

时间:2010-12-24  来源:姜 萌@cnblogs

1.对已经下载过的资源不再重复下载。

2.下载过的资源要缓存,一方面存在内存中,一方面存在isolatedstorage中。

实现这些功能会极大的提高用户体验,所我们有必要设计一个带有缓存控制能力的资源管理器。

复用已有的DownloadDelegater

搞开发的嘛,不可能每一个需求都单独写一片代码,这要将对象的职责分离清楚,复用还是很容易的。

我们定义需求接口:

public interface IWebClientResourceService 
    { 
        void Load(Uri uri, DownloadResultEventHandler callback); 
        void PutIsolatedStorageToMemoryCache(Uri uri); 
        void PutMemoryCacheToIsolatedStorage(Uri uri); 
        void RemoveCache(Uri uri); 
    }

 

 

Load方法会下载指定uri的资源,如果之前已经在下载过就不会重复下载。

PutIsolatedStorageToMemoryCache将隔离存储中的数据加载到内存中。

PutMemoryCacheToIsolatedStorage将内存数据保存到隔离存储。

下面通过组合的方式复用之前的DownloadDelegater。

WebClientResourceService namespace Sopaco.Silverlight.Insfrastructure.Net.DownloadActivator
{
    public class WebClientResourceService : Sopaco.Silverlight.Insfrastructure.Net.DownloadActivator.IWebClientResourceService
    {
        public static readonly WebClientResourceService Instance;
        static WebClientResourceService()
        {
            Instance = new WebClientResourceService();
        }
        private Dictionary<Uri, DownloadTask> _resourceCacher = new Dictionary<Uri, DownloadTask>();
        private DownloadDelegater _downloadDelegater = new DownloadDelegater();

        private object _locker_ResourceCacher = new object();

        public void Load(Uri uri, DownloadResultEventHandler callback)
        {
            #region 检查是否已经有缓存
            lock (_locker_ResourceCacher)
            {
                if (_resourceCacher.ContainsKey(uri))
                {
                    if (callback != null)
                    {
                        var task = _resourceCacher[uri];
                        callback(task.CloneStream, task.Status);
                    }
                    return;
                }
                _resourceCacher[uri] = new DownloadTask()
                {
                    Uri = uri,
                    Stream = null,
                    Status = DownloadStatus.UnStarted
                };
            }
            #endregion
            #region 使用下载器下载
            _downloadDelegater.Download(uri, (stream, status) => 
                    {
                        onResultArrive(uri, status, stream);
                        if(callback != null)
                            callback(stream, status);
                    });
            if (_resourceCacher[uri].Status == DownloadStatus.UnStarted)//防止过快下载而使状态不同步
            {
                _resourceCacher[uri].Status = DownloadStatus.Running;
            }
            #endregion
        }
        /// <summary>
        /// 移除缓存
        /// 未防止缓存内容过大导致内存持续消耗,应该适当调用此方法移出缓存(或者存放在隔离存储中?)
        /// </summary>
        public void RemoveCache(Uri uri)
        {
            lock (_locker_ResourceCacher)
            {
                if (_resourceCacher.ContainsKey(uri))
                {
                    var cacheObj = _resourceCacher[uri];
                    if(_resourceCacher.Remove(uri))
                    {
                        cacheObj.Dispose();
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("移除资源异常:无法移除资源@" + System.Reflection.MethodInfo.GetCurrentMethod().ToString());
                    }
                }
            }
        }
        /// <summary>
        /// 将一个资源缓存到隔离存储中
        /// </summary>
        /// <param name="uri"></param>
        public void PutMemoryCacheToIsolatedStorage(Uri uri)
        {
            if(_resourceCacher.ContainsKey(uri))
            {
                IsolateStorageRespository.Instance.AddWithOverwrite(uri.ToString(), _resourceCacher[uri]);
            }
        }
        /// <summary>
        /// 从隔离存储中将一个资源缓存起来
        /// </summary>
        /// <param name="uri"></param>
        public void PutIsolatedStorageToMemoryCache(Uri uri)
        {
            if (_resourceCacher.ContainsKey(uri))
            {
                var cache = IsolateStorageRespository.Instance.Get<DownloadTask>(uri.ToString());
                if(cache != null)
                {
                    _resourceCacher[uri] = cache;
                }
            }
        }
        private void onResultArrive(Uri uri, DownloadStatus status, MemoryStream stream)
        {
            _resourceCacher[uri].Status = status;
            _resourceCacher[uri].Stream = stream;
        }
    }
}

 

 

进一步使用

上面的WebClientResourceService功能还是有些“大一统”,我们可以进一步针对一些特定资源进行应用。

示例需求:对于图片资源包和一些零散的没有放到资源包里的图片资源,一旦下载下来将其放到隔离存储中,下次再需要下载此图片时就直接从隔离存储中取得(如果资源有更新的话将隔离存储中的数据清除就ok)。

GameImageResService namespace Sopaco.Silverlight.GameFramewrok.GameRes
{
    /// <summary>
    /// 应用WebClientResourceService定制的一个游戏资源服务模块
    /// </summary>
    public class GameImageResService
    {
        #region make it a singleton
        public static readonly GameImageResService Instance;
        static GameImageResService()
        {
            Instance = new GameImageResService();
        }
        public GameImageResService()
        {

        }
        #endregion
        private static readonly string IMG_ZIP_XML = "resconfig.xml";
        private WebClientResourceService _resourceService = WebClientResourceService.Instance;
        private Dictionary<Uri, BitmapImage> _imageCache = new Dictionary<Uri, BitmapImage>();
        private Dictionary<string, BitmapImage> _namedImageCache = new Dictionary<string, BitmapImage>();
        /// <summary>
        /// 图片资源
        /// </summary>
        public void GetBitmapImage(Uri uri, Action<BitmapImage> callback)
        {
            if(_imageCache.ContainsKey(uri))
            {
                callback(_imageCache[uri]);
                return;
            }
            _resourceService.Load(uri, (stream, status) => 
                {
                    if(status == DownloadStatus.Completed)
                    {
                        var image = new BitmapImage();
                        image.SetSource(stream);
                        _imageCache[uri] = image;
                        _resourceService.PutMemoryCacheToIsolatedStorage(uri);//图片资源由GameResService托管,将WebClientResourceService中的缓存持久化
                        callback.ExecuteSecurity(image);
                    }
                    else
                    {
#if DEBUG
                        throw new Exception("error in resource downloading");
#endif
                    }
                });
        }
        /// <summary>
        /// 载入一个zip资源包中的图片资源
        /// </summary>
        /*配置文件格式
         * resconfig.xml
         * <?……?>
         * <AppRoot>
         * <ImgResSection><Image key="……" uri="……" /></ImgResSection>
         * </AppRoot>
         * #endregion
         */
        public void GetBitmapImageInZip(Uri uri, Action onZipLoaded, Action onResourcesLoad)
        {
            _resourceService.Load(uri, (stream, status) =>
            {
                if(status != DownloadStatus.Completed)
                {
#if DEBUG
                    throw new Exception("error in download resource");
#endif
                }
                onZipLoaded.ExecuteSecurity();
                StreamResourceInfo info = new StreamResourceInfo(stream, null);
                using (var reader = new StreamReader(Application.GetResourceStream(info, new Uri(IMG_ZIP_XML, UriKind.Relative)).Stream))
                {
                    var xmlReader = XmlReader.Create(reader);
                    while(xmlReader.Read())
                    {
                        if(xmlReader.IsStartElement("ImgResSection"))
                        {
                            while(xmlReader.Read())
                            {
                                if(xmlReader.IsStartElement("Image"))
                                {
                                    xmlReader.MoveToAttribute("key");
                                    xmlReader.ReadAttributeValue();
                                    string imgKey = xmlReader.Value;
                                    xmlReader.MoveToAttribute("uri");
                                    xmlReader.ReadAttributeValue();
                                    var targetUri = new Uri(xmlReader.Value, UriKind.RelativeOrAbsolute);
                                    var bitmapStream = Application.GetResourceStream(info, targetUri).Stream;
                                    var image = new BitmapImage();
                                    image.SetSource(bitmapStream);
                                    _namedImageCache[imgKey] = image;
                                }
                            }
                        }
                    }
                }
                onResourcesLoad.ExecuteSecurity();
                #region zip图片资源包由GameResService托管,将WebClientResourceService中的缓存持久化
                _resourceService.PutMemoryCacheToIsolatedStorage(uri);
                #endregion
            });
        }
        public BitmapImage GetImageByUri(Uri uri)
        {
            if (!_imageCache.ContainsKey(uri))
                return null;
            return _imageCache[uri];
        }
        public BitmapImage GetImageBySpecialName(string key)
        {
            if(!_namedImageCache.ContainsKey(key))
                return null;
            return _namedImageCache[key]; 
        }
    }
}

 

 

本文源码下载

 最后祝大家圣诞快乐Merry Christmas!

相关阅读 更多 +
排行榜 更多 +
我的武侠梦手游下载

我的武侠梦手游下载

角色扮演 下载
快乐连连看下载免费版

快乐连连看下载免费版

休闲益智 下载
泛滥死者布道手机版下载

泛滥死者布道手机版下载

角色扮演 下载