Unity图片加载器

在http://www.tuicool.com/articles/ZFrMZnM的基础上对AsyncImageDownload进行了完善,完整代码如下:


using UnityEngine;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using System;
/// 
/// 图片(Texture)加载类
/// 三级缓存:1、如果在内存中,则先从内存获取;2、没有则查看本地是否存在,存在则从本地获取;3、没有则再从网络进行获取并保存到本地。
/// 
public class AsyncImageDownload : MonoBehaviour
{
    /// 
    ///  默认图片
    /// 
    public Texture placeholder;

    /// 
    /// 单例
    /// 
    public static AsyncImageDownload Instance = null;

    /// 
    /// 本地图片保存路径。如果是android环境,Application.persistentDataPath值为/storage/emulated/legacy/Android/data/com.xxx.xxx/files/
    /// 
    private string imageCacheRootPath = Application.persistentDataPath + "/ImageCache/";

    /// 
    /// 缓存在内存里的texture,重复利用。key是url对应图片保存成本地文件的绝对路径。
    /// texture采用弱引用方式,当系统需要回收时这里不会因为强引用阻止回收。
    /// 
    private Dictionary textureCache = new Dictionary();

    /// 
    /// 应用开始运行时,可以调用此方法进行初始化
    /// 
    /// AsyncImageDownload单例对象
    public static AsyncImageDownload CreateSingleton()
    {
        if (!Directory.Exists(Application.persistentDataPath + "/ImageCache/"))
        {
            Directory.CreateDirectory(Application.persistentDataPath + "/ImageCache/");
        }
        GameObject obj = new GameObject();
        obj.AddComponent();

        AsyncImageDownload loader = obj.GetComponent();
        Instance = loader;
        loader.placeholder = Resources.Load("default_cover") as Texture;// 默认图片
        Debug.Log("image save path : " + Instance.imageCacheRootPath);
        return loader;
    }

    /// 
    /// 根据url加载对应图片。
    /// 
    /// 图片url
    /// UITexture
    /// 加载完成时的回调
    /// 是否需要缓存到内存中(如果非长时间显示在页面,不建议缓存)
    public void SetAsyncImage(string url, UITexture texture, Action action = null, bool needCache = true)
    {
        if (string.IsNullOrEmpty(url))
        {
            Debug.LogWarning("[SetAsyncImage] url is null.");
            return;
        }

        // 只有需要缓存时才从内存中查找
        if (needCache)
        {

            // 从内存获取
            if (getFromCache(imageCacheRootPath + url.GetHashCode(), texture))
            {

                if (action != null)
                {
                    action();
                }
                return;
            }
        }

        //判断是否是第一次加载这张图片(以url的hashcode作为文件名)
        if (!File.Exists(imageCacheRootPath + url.GetHashCode()))
        {
            //如果之前不存在缓存文件
            texture.StopCoroutine("DownloadImage");//UITexture.StopCoroutine可以停止之前的已经无用的协程
            texture.StartCoroutine(DownloadImage(url, texture, action, needCache));
        }
        // 从本地加载
        else
        {
            texture.StopCoroutine("LoadLocalImage");
            texture.StartCoroutine(LoadLocalImage(imageCacheRootPath + url.GetHashCode(), texture, action, needCache));
        }

    }

    /// 
    /// 加载本地图片。缓存到内存里。
    /// 
    /// 本地文件绝对路径
    /// UITexture
    /// 加载完成时的回调
    public void SetLocalImage(string path, UITexture texture, Action action = null)
    {
        if (string.IsNullOrEmpty(path))
        {
            Debug.LogWarning("[SetLocalImage] path is null.");
            return;
        }

        // 从内存获取
        if (getFromCache(path, texture))
        {

            if (action != null)
            {
                action();
            }
            return;
        }

        // 先判断该文件是否存在,不存在直接返回(这样会显示默认图片);如果不做这个判断进入LoadLocalImage,界面上会显示成红色问号。
        FileInfo fi = new FileInfo(path);
        if (!fi.Exists)
        {
            Debug.LogError("Path is Not Exists! " + path);
            return;
        }
        texture.StopCoroutine("LoadLocalImage");
        texture.StartCoroutine(LoadLocalImage(path, texture, action));
    }

    /// 
    /// 清空指定key的缓存
    /// 
    /// 
    public void clearCache(string filePath)
    {
        if (textureCache.ContainsKey(filePath))
        {
            textureCache.Remove(filePath);
        }
    }

    /// 
    /// 
    /// 
    /// 图片url
    /// UITexture
    /// 加载完成时的回调
    /// 是否需要缓存到内存中
    /// 
    IEnumerator DownloadImage(string url, UITexture texture, Action action = null, bool needCache = true)
    {
        
        int filename = url.GetHashCode();
        Debug.Log("[DownloadImage]downloading new image : " + filename);

        yield return new WaitForSeconds(0.008f);//如果界面频繁快速切换,之前的图片根本不需要加载,所以这里稍微延迟一会儿再请求网络。

        WWW www = new WWW(url);
        yield return www;

        if (www.error != null)
        {
            Debug.LogWarning("[DownloadImage] www.error : " + www.error);
            if (action != null)
            {
                action();
            }
        }
        else
        {
            Debug.Log("[DownloadImage]download ok : " + filename);
            Texture2D image = www.texture;
            // The data must be an image in JPG or PNG format. If the data is not a valid image, the generated texture will be a small image of a question mark.(红色问号,大小为8*8)
            if (image == null || (image.width == 8 && image.height == 8))//如果image为空,或者为红色问号(无效图片)。
            {
                Debug.LogError("[DownloadImage]www.texture is null or a question mark, return.");
            	if (action != null)
            	{
                	action();
            	}
            }
            else
            {
                image.wrapMode = TextureWrapMode.Clamp;//将Texture的循环模式设为拉伸,Texture边界设为拉伸就不会出现白线。默认是平铺,如果是平铺的话,可能会出现两张图片交界处显示白线的问题。
                texture.mainTexture = image;

                if (needCache)
                {
                    textureCache[imageCacheRootPath + url.GetHashCode()] = new WeakReference(image);
                }

                if (action != null)
                {
                    action();
                }

                //将图片保存至缓存路径
                byte[] pngData = www.bytes;
                Debug.Log("[DownloadImage] " + filename + " , size : " + (pngData.Length / 1024) + "KB");
                File.WriteAllBytes(imageCacheRootPath + filename, pngData);
            }
        }
    }

    IEnumerator LoadLocalImage(string filePath, UITexture texture, Action action = null, bool needCache = true)
    {
        Debug.Log("getting local image :" + filePath);
        
        yield return new WaitForSeconds(0.008f);
        WWW www = new WWW("file:///" + filePath);
        yield return www;

        if (www.error != null)
        {
            Debug.LogWarning("[LoadLocalImage] www.error : " + www.error);
            DeleteFile(filePath);
        }
        else
        {
            Texture2D image = www.texture;
            //The data must be an image in JPG or PNG format. If the data is not a valid image, the generated texture will be a small image of a question mark.(红色问号,大小为8*8)
            if (image == null || (image.width == 8 && image.height == 8))//如果image为空,或者为红色问号(无效图片)。
            {
                Debug.LogError("www.texture is null or a question mark, delete it.");
                DeleteFile(filePath);
            }
            else
            {
                image.wrapMode = TextureWrapMode.Clamp;//将Texture的循环模式设为拉伸,Texture边界设为拉伸就不会出现白线。默认是平铺,如果是平铺的话,可能会出现两张图片交界处显示白线的问题。
                //直接贴图
                texture.mainTexture = image;

                if (needCache)
                {
                    textureCache[filePath] = new WeakReference(image);
                }
            }
        }
        if (action != null)
        {
            action();
        }
    }


    /// 
    /// 从textureCache读取
    /// 
    /// 
    /// 
    /// 
    private bool getFromCache(string localPath, UITexture texture)
    {
        if (textureCache.ContainsKey(localPath))
        {
            WeakReference wr = textureCache[localPath];
            if (wr != null && wr.IsAlive)
            {
                texture.mainTexture = (Texture2D)wr.Target;
                if (texture.mainTexture == null)// 有可能在获取到的瞬间被回收了
                {
                    return false;
                }
                return true;
            }
        }
        return false;
    }

    private void DeleteFile(string filePath)
    {
        FileInfo fi = new FileInfo(filePath);
        if (fi.Exists)
        {
            Debug.LogWarning("[DeleteFile] delete this file : " + filePath);
            fi.Delete();
        }
    }
   
}




你可能感兴趣的:(unity,图片,加载)