游戏蛮牛学习群(纯技术交流,不闲聊):539178957
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

首页   >   博客   >   小谭哥

图片下载管理 热度 2

2017-12-28 15:50
1 个评论 | 阅读 464 | 收藏 | 举报
之前做一个纯UI项目时,从服务器拉取了大量的图片地址,UI切换过程中和列表翻页过程中,遇到了同时下载大量图片以及重复下载的问题。所以编写了一套下载管理脚本。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

public class TextureDownLoadManager : MonoBehaviour
{
    public static TextureDownLoadManager Instance;

    /// <summary>
    /// 存储已经下载过的图片和地址
    /// </summary>
    Dictionary<string, Texture2D> m_pathSumTextureDic = new Dictionary<string, Texture2D>();
    /// <summary>
    /// 存储已经下载过得图片地址(辅助字典做清除)
    /// </summary>
    List<string> m_savePathList = new List<string>();
    /// <summary>
    /// 存储正在下载的图片地址和回调事件(用于下载完成后响应事件)
    /// </summary>
    Dictionary<string, UnityAction<string, Texture2D>> m_downingDic = new Dictionary<string, UnityAction<string, Texture2D>>();
    /// <summary>
    /// 允许同时开启下载的最大数量
    /// </summary>
    const int DONWLOADCOUNT = 3;
    /// <summary>
    /// 当前开启的下载数量
    /// </summary>
    int m_currentDownLength = 0;
    /// <summary>
    /// m_pathSumTextureDic字典的最大存储值(避免内存占用过多)
    /// </summary>
    const int TOTALDICCOUNT = 100;
    /// <summary>
    /// 存储等待下载的地址和回调(用于同时下载的数量超过了DONWLOADCOUNT时,放入该字典中)
    /// </summary>
    Dictionary<string, UnityAction<string, Texture2D>> m_downWaitDic = new Dictionary<string, UnityAction<string, Texture2D>>();
    /// <summary>
    /// 同时下载的数量超过了DONWLOADCOUNT时把下载地址放入该队列中当下载完成后从该队列里取出
    /// </summary>
    Queue<string> m_waitPathQueue = new Queue<string>();

    private WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();

    //是否需要清理无用的资源
    bool m_isNeedUnload;

    public Dictionary<string, Texture2D> PathSumTextureDic
    {
        get
        {
            //如果list长度大于限制长度 则移除最早的那张图
            if (m_pathSumTextureDic.Count > TOTALDICCOUNT)
            {
                //移除前十张图
                for (int i = 0; i < 10; i++)
                {
                    m_pathSumTextureDic.Remove(m_savePathList[0]);
                    m_savePathList.RemoveAt(0);
                    m_isNeedUnload = true;
                }
            }
            return m_pathSumTextureDic;
        }
    }

    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
        }
        DontDestroyOnLoad(this.gameObject);
    }

    public void UnLoad()
    {
        if (m_isNeedUnload)
        {
            Resources.UnloadUnusedAssets();
            m_isNeedUnload = false;
        }
    }

    public void AddDownLoadItem(string path, UnityAction<string, Texture2D> callBack)
    {
        if (string.IsNullOrEmpty(path) || (!path.StartsWith("file") && !path.StartsWith("http")))
        {
            Debug.LogError("传入的地址不正确:" + path);
            return;
        }
        if (PathSumTextureDic.ContainsKey(path))//如果已经存储
        {
            callBack(path, PathSumTextureDic[path]);
            //将最近一次取过的图片放在列表最后,方便字典做清理
            m_savePathList.Remove(path);
            m_savePathList.Add(path);
        }
        else if (m_downingDic.ContainsKey(path))//如果该地址正在下载(防止同一地址多次下载)
        {
            //将CallBack加入正在下载字典里
            m_downingDic[path] += callBack;
        }
        else//没有开启过下载
        {
            if (m_downWaitDic.ContainsKey(path))//但是地址已经再等待下载字典里(防止同一地址多次下载)
            {
                m_downWaitDic[path] += callBack;//则将回调添加进等待下载的字典里
            }
            else
            {
                m_waitPathQueue.Enqueue(path);//添加进等待队列
                m_downWaitDic.Add(path, callBack);//添加进等待下载的字典里
            }
            CheckDownldQueue();
        }
    }

    /// <summary>
    /// 检查等待下载的队列
    /// </summary>
    void CheckDownldQueue()
    {
        if (m_currentDownLength >= DONWLOADCOUNT)
            return;
        if (m_waitPathQueue.Count == 0)
            return;
        //取出最先添加进下载队列的地址和回调事件
        var path = m_waitPathQueue.Dequeue();
        var callback = m_downWaitDic[path];
        m_downWaitDic.Remove(path);//从等待下载字典里清除
        m_downingDic.Add(path, callback);//添加进正在下载的字典中
        m_currentDownLength++;
        StartCoroutine(DownLoad(path));
    }
    /// <summary>
    /// 开启一个下载协程
    /// </summary>
    /// <param name="path"></param>
    IEnumerator DownLoad(string path)
    {
        WWW www = new WWW(path);
        yield return www;
        if (www.error != null)
        {
            Debug.Log(www.error);
            m_downingDic[path](path, null);
            m_downingDic.Remove(path);
        }
        else
        {
            Texture2D texture = www.texture;
            if (!PathSumTextureDic.ContainsKey(path))
            {
                PathSumTextureDic.Add(path, texture);
                m_savePathList.Add(path);
            }
            else
            {
                PathSumTextureDic[path] = texture;
            }
            //移除正在下载的图片列表
            if (m_downingDic.ContainsKey(path))
            {
                //响应正在下载的List里各Item的CallBack
                m_downingDic[path](path, texture);
                m_downingDic.Remove(path);
            }
        }
        m_currentDownLength--;
        CheckDownldQueue();
    }
}

2 0

评论 (1 个评论)

回复 美国牛排 2018-1-3 10:11
谭哥牛逼

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册帐号
返回顶部