首页 > 代码库 > 【Unity3d】【项目学习心得】从资源服务器下载资源(二)

【Unity3d】【项目学习心得】从资源服务器下载资源(二)

继上篇的基础准备 从资源服务器下载资源(一) 

我们现在继续进一步完成 LoadManager 管理类。

管理类因为在全局中都是存在的,所以应该作为单例存在。

因为LoadManager 类是管理多个 LoadRequest的,所以我们需要存储当前正在下载的LoadRequest,以及下载完成的 LoadRequest。

另外,我们为了防止太多下载线程占用过多资源,我们对于下载的线程个数做一定的限制,如项目里面的最大线程数为2,所以我们需要一个存储LoadRequest的等待队列。

根据以上分析,分别如下:

 public static LoadManager instance;
    public int MAX_LOAD_REQUEST = 2;

    private Dictionary<string, LoadRequest> loadDict = new Dictionary<string, LoadRequest>();
    private Dictionary<string, LoadRequest> waitDict = new Dictionary<string, LoadRequest>();
    private Dictionary<string, LoadParam> completeDict = new Dictionary<string, LoadParam>();

另外,既然有下载队列的存在,就有下载优先级,我们可以多一个存储下载任务的优先级,然后根据优先级进行下载。

当然,项目里面虽然有了下载优先级的存储,但是并没有进行排序,在进行下载任务创建的时候,也都统一使用了Normal优先级。

所以在此我们先跟着创建,等到以后需要使用优先级的时候再进行排序。

    private List<string> priorityList = new List<string>();

接下来我们开始实现代码:

1. 首先实现单例:

    /// <summary>
    ///  返回实例
    /// </summary>
    /// <returns></returns>
    public static LoadManager getInstance() {
        if (instance == null) {
            instance = new LoadManager();
        }
        return instance;
    }

2. 我们实现一个函数,功能是根据优先级,从等待队列里面移除一个任务到下载队列里。

    /// <summary>
    /// 根据优先级,从等待队列里面移除一个任务到下载队列里
    /// </summary>
    public void MoveRequestFromWaitDictToLoadDict() {
        isLoading = loadDict.Count > 0;
        if (priorityList.Count > 0) {
            if (waitDict.ContainsKey(priorityList[0])) {
                LoadRequest request = waitDict[priorityList[0]];
                waitDict.Remove(priorityList[0]);
                priorityList.RemoveAt(0);
                Load(request.requestURL, request.completeFunction, request.customParams, request.fileType, request.priotiry, request.errorFunction, request.processFunction);
            }
        }
    }


3.上面的Load()函数是加载新的LoadRequest。

在加载新的LoadRequest时,我们要进行判断,例如同个下载任务可能是由不同的组件请求发起的;

① 这个时候我们当然不能再去下载一次,所以只需判断completeDict里面是否已经下载过了,如果是,就直接使用即可。

② 另外,当有相同的请求时,不过此时下载还没完成(正在下载中),此时我们只需把回调函数加进回调队列即可。

③ 相同的,如果相同的请求在等待队列,也跟②一样处理。

④ 最后就剩下是,从没下载过的情况,此时我们要看当前下载的线程是否超过最大限制,如果是,则把任务加到等待队列,如果不是,则可马上下载

具体实现为下:


/// <summary>
    /// 读取资源
    /// </summary>
    public void Load(string url, LoadRequest.DownCompleteDelegate completeFunc, object customParam = null, string fileType = "", int  priority = 2, LoadRequest.ErrorDelegate errorFunc = null, LoadRequest.ProcessDelegate processFunc = null) {
        url = url.Trim();
        if (string.IsNullOrEmpty(url)) return;
       
        if (completeDict.ContainsKey(url)) {
            // 已下载资源,直接调用回调函数
            if (customParam != null) {
                completeDict[url].param = customParam;
            }
            try {
                completeFunc.Invoke(completeDict[url]);
            } catch (Exception exception) {
                Debug.LogWarning("exception:" + exception.Message);
            }
        } else if (loadDict.ContainsKey(url)) {
            // 已经提交相同请求,但是没有下载完成
            loadDict[url].completeFunction += completeFunc;
            loadDict[url].processFunction += processFunc;
            loadDict[url].errorFunction += errorFunc;
            loadDict[url].customParams.Add(customParam);
        } else if (waitDict.ContainsKey(url)) {
            // 已经提交相同请求,但是还没轮到加载
            loadDict[url].completeFunction += completeFunc;
            loadDict[url].processFunction += processFunc;
            loadDict[url].errorFunction += errorFunc;
            loadDict[url].customParams.Add(customParam);
        } else {
            // 未加载过的
            if (loadDict.Count < MAX_LOAD_REQUEST) {
                isLoading = true;
                LoadRequest loadRequest = new LoadRequest(url, customParam, fileType, completeFunc, errorFunc, processFunc);
                if (customParam != null && customParam.GetType().ToString() == "System.Collections.Generic.List`1[System.Object]") {
                    loadRequest.customParams = (List<object>)customParam;
                }
                loadDict.Add(url, loadRequest);
            } else {
                // 已达到最大加载数目,加入等待队列
                LoadRequest loadRequest = new LoadRequest();
                loadRequest.requestURL = url;
                loadRequest.completeFunction = completeFunc;
                loadRequest.errorFunction = errorFunc;
                loadRequest.processFunction = processFunc;
                loadRequest.customParams.Add(customParam);
                loadRequest.fileType = fileType;
                loadRequest.priotiry = priority;
                waitDict.Add(url, loadRequest);
                priorityList.Add(url);
                priorityList = priorityList.OrderBy(s => waitDict[s].priotiry).ToList();
            }
        }
    }






















【Unity3d】【项目学习心得】从资源服务器下载资源(二)