1. 程式人生 > >Unity+NGUI打造網路圖片非同步載入與本地快取工具類(一)

Unity+NGUI打造網路圖片非同步載入與本地快取工具類(一)

我們在移動端的開發中,非同步網路圖片載入用的非常的多,在unity當中雖然有AssetBundle的存在,一般是先載入好遊戲資源然後再進入場景,但是還有不少地方能夠用到非同步網路圖片的載入以及其快取機制。

我之前也寫過兩個版本的ios中的非同步網路圖片載入helper類,所以今天按照同樣的思路,也想做一個好用的helper類給大家使用以及簡單的說下實現原理。

首先我們載入一張網路圖片,要做的事情分步來講為:

0.開始之前設定一張固定的圖片作為佔位圖(placeholder),表示我們的圖片還沒載入好,來填充當前圖片控制元件區域,讓使用者知道

1.這個圖片有個url地址,我們的程式第一次載入這個url地址的圖片時

a.非同步開始下載這張圖片

b.儲存到某個指定的目錄

c.將圖片控制元件上佔位圖替換為下載好的圖片,可以適當的新增圖片切換動畫(動畫本文略)

2.我們的程式已經載入過這個url地址的圖片

a.從上次存進的目錄中讀取檔案,轉換為圖片

b.將圖片控制元件上佔位圖替換為下載好的圖片

總的來說我們的程式應該是在第一次載入一批網路圖片的時候,是需要哪張下哪張,然後顯示出來,而後,是可以直接從檔案系統中去讀取的(第三種情況,從記憶體中直接讀取,取決於裝置配置,這裡就不做了)

開始做這個工具類之前,先要知道一些unity的特殊限制:

1.MonoBehaviour基類的成員方法 StartCoroutine開啟非同步任務是不支援靜態方法中呼叫的

2.MonoBehaviour基類的子類不能直接使用關鍵字new 來建立,相應的,需要建立一個空的GameObject,然後呼叫這個object的AddComponent方法來例項化,也就是說unity中的指令碼物件都依附於遊戲物件才能被執行

3.由於unity的跨平臺特性,每個不同的平臺的檔案目錄結構有區別

基於上述一些特殊性,我打算把這個工具類作成一個MonoBehaviour的子類,並以單例的形式讓其他指令碼呼叫,其中的非同步網路請求就可以使用StartCoroutine函數了

首先是這個單例的實現方法:

using UnityEngine;
using System.Collections;
using System.IO;

public class AsyncImageDownload :MonoBehaviour {

	public  Texture placeholder;
	public static AsyncImageDownload  Instance=null;

	private   string path=Application.persistentDataPath+"/ImageCache/" ;

	//構建單例
	public static AsyncImageDownload CreateSingleton()
	{
		if (!Directory.Exists(Application.persistentDataPath+"/ImageCache/")) {
			Directory.CreateDirectory(Application.persistentDataPath+"/ImageCache/");
		}

		GameObject obj = new GameObject ();
		obj.AddComponent<AsyncImageDownload> ();

		AsyncImageDownload loader= obj.GetComponent<AsyncImageDownload>();
		Instance=loader;
		loader.placeholder=Resources.Load("placeholder") as Texture;
		return loader;

	}
這裡沒有使用建構函式來建立單例,原因是MonoBehaviour的子類壓根不支援new關鍵字,所以怎麼去寫建構函式呢

然後這個構建單例的方法是跟構造方法差不多的,只是不是去new出來,而是類名.方法名()來建立這個單例,在建立單例的時候需要建立一個空白遊戲體來依附我們的指令碼元件,並且把靜態成員Instance指向創建出來的這個單例,多次使用這個單例的時候只需要使用 類名.Instance()來獲取已經存在的這個指令碼元件單例。

這裡的Resources.Load(“placeholder”)需要注意,用程式碼讀取專案目錄中的圖片資源並轉換成Texutre物件,需要再Project視窗下的Assets中建立Resources資料夾,然後匯入任何一張圖片進去,程式碼中獲取他不需要加字尾名。

這個指令碼寫好以後,我們的程式初始化的時候應該執行以下程式碼來建立這個單例:

AsyncImageDownload.CreateSingleton()

而後,給某個控制元件載入網路圖片,我們應該給這個單例加一個方法public  void SetAsyncImage(string url,UITexture texture),那麼簡化的寫法就可以寫為:
AsyncImageDownload.Instance.SetAsyncImage ("http://www.cfanz.cn/uploads/jpg/2013/07/13/0/XEPLd7d2C5.jpg", page.GetComponentInChildren<UITexture> ());
這個方法會在這篇博文的第二部分中完成