UILoadMgr的管理思路
一般采用单例设计模式
字段:
预加载包字典
对象池字典
方法:
加载package
加载packages
获得Object
处理包之间依赖的关系
加载组件
加载纹理
释放纹理
移除包
释放Object
代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FairyGUI;
using UnityEngine.ResourceManagement.AsyncOperations;
using System;
public class UILoadMgr
{
private static UILoadMgr instance = null;
public static UILoadMgr Instance
{
get
{
if (instance == null)
return new UILoadMgr();
return instance;
}
}
private const string address = "Assets/ZBuild/Build/UI/{0}/{1}";
private UILoadMgr()
{
//UIConfig.defaultFont=""
}
private struct HandleStruct
{
public Action callback;
public bool isThemePark;
}
private Dictionary<string, Queue<AsyncOperationHandle>> dicHandle = new Dictionary<string, Queue<AsyncOperationHandle>>();
private Dictionary<string, Queue<HandleStruct>> dicPkgCallback = new Dictionary<string, Queue<HandleStruct>>();
private Dictionary<string, Queue<ModelViewStruct>> dicCallback = new Dictionary<string, Queue<ModelViewStruct>>();
private static List<string> comPkgList = new List<string> { "Icon" };
private static Dictionary<string, int> pkgRefCountDic = new Dictionary<string, int>();
private static Dictionary<string, GObjectPool> dicGObjectPool = new Dictionary<string, GObjectPool>();
public void LoadPackage(string modelName,Action callback=null)
{
Queue<AsyncOperationHandle> handles;
if(dicHandle.TryGetValue(modelName,out handles))
{
callback?.Invoke();
return;
}
Queue<HandleStruct> actions;
if(dicPkgCallback.TryGetValue(modelName,out actions))
{
actions.Enqueue(new HandleStruct() { callback = callback, isThemePark = false });
return;
}
else
{
dicPkgCallback[modelName] = new Queue<HandleStruct>();
dicPkgCallback[modelName].Enqueue(new HandleStruct() { callback = callback, isThemePark = false });
}
AsyncOperationHandle handleBin = default(AsyncOperationHandle);
handleBin = AddressableTools.LoadBinary(string.Format(address,modelName,modelName)+ "_fui.bytes", bytes =>
{
AddHandle(modelName, handleBin);
UIPackage.AddPackage(bytes, modelName, (string name,string extension,System.Type type,PackageItem item)=> {
AddressableTools.Load(string.Format(address, modelName, name + extension), data => {
item.owner.SetItemAsset(item, data, DestroyMethod.Unload);
});
});
while(dicPkgCallback[modelName].Count>0)
{
var v = dicPkgCallback[modelName].Dequeue();
v.callback?.Invoke();
}
dicPkgCallback[modelName].Clear();
dicPkgCallback.Remove(modelName);
});
}
public void PreLoadPackages(Action callback=null)
{
LoadPackages(comPkgList, callback);
}
public void LoadPackages(List<string> list,Action callback=null)
{
if(list==null || list.Count==0)
{
callback?.Invoke();
return;
}
int count = 0;
for (int i = 0; i < list.Count; i++)
{
Load(list[i], null, com => {
count++;
if (count >= list.Count)
callback?.Invoke();
},false);
}
}
private Transform uiPoolTransformRoot;
public GObject GetPoolObject(string modelName,string viewName)
{
GObject obj;
GObjectPool pool;
string resourceURL = UIPackage.NormalizeURL(UIPackage.URL_PREFIX + modelName + "/" + viewName);
if(resourceURL==null)
{
Debug.LogError(modelName + "/" + viewName + "没有设置导出!!!");
return null;
}
if(!dicGObjectPool.TryGetValue(resourceURL,out pool))
{
pool = new GObjectPool(uiPoolTransformRoot);
dicGObjectPool[resourceURL] = pool;
}
bool isCreate = pool.count == 0;
obj = pool.GetObject(resourceURL);
if(isCreate)
{
string pkgId = obj.packageItem.owner.id;
int count;
if(!pkgRefCountDic.TryGetValue(pkgId,out count))
{
pkgRefCountDic[pkgId] = 1;
}
else
{
pkgRefCountDic[pkgId] = ++count;
}
}
return obj;
}
public void RecyclePoolObject(GObject obj)
{
if (obj == null) return;
string resouceURL = obj.resourceURL;
GObjectPool pool;
if(dicGObjectPool.TryGetValue(resouceURL,out pool))
{
pool.ReturnObject(obj);
}
else
{
Debug.LogError(string.Format("回收对象{0},没有在对象内", obj.name));
}
}
public void ClearPoolObject(string resourceURL)
{
GObjectPool pool;
if(dicGObjectPool.TryGetValue(resourceURL,out pool))
{
pool.Clear();
}
}
private struct ModelViewStruct
{
public string modelName;
public string viewName;
public bool isCreate;
public Action<GObject> callback;
}
private List<string> GetNoLoadedDependenciesPackages(string[] dependenciesPackages)
{
List<string> list = new List<string>();
Array.ForEach<string>(dependenciesPackages, v => {
if(!comPkgList.Contains(v)&& !list.Contains(v)&&UIPackage.GetByName(v)==null)
{
list.Add(v);
}
});
return list;
}
public void Load(string modelName,string viewName=null,Action<GObject> callback=null,bool isCreate=false,string[] dependenciesPackages=null)
{
List<string> pkgNames;
if(dependenciesPackages!=null&& dependenciesPackages.Length>0&&(pkgNames=GetNoLoadedDependenciesPackages(dependenciesPackages)).Count>0)
{
LoadPackages(pkgNames, () => {
LoadMain(modelName, viewName, callback, isCreate);
});
}
else
{
LoadMain(modelName, viewName, callback, isCreate);
}
}
private void LoadMain(string modelName, string viewName = null, Action<GObject> callback = null,bool isCreate=false)
{
Queue<ModelViewStruct> actions;
if(dicCallback.TryGetValue(modelName,out actions)&& actions!=null)
{
actions.Enqueue(new ModelViewStruct() { modelName = modelName, viewName = viewName, callback = callback, isCreate = isCreate });
return;
}
else
{
dicCallback[modelName] = new Queue<ModelViewStruct>();
dicCallback[modelName].Enqueue(new ModelViewStruct() { modelName = modelName, viewName = viewName, callback = callback, isCreate = isCreate });
}
LoadPackage(modelName, () => {
while(dicCallback[modelName].Count>0)
{
var v = dicCallback[modelName].Dequeue();
if(!v.isCreate)
{
v.callback?.Invoke(null);
continue;
}
if(v.callback!=null)
{
var com = GetPoolObject(v.modelName, v.viewName).asCom;
v.callback(com);
}
}
dicCallback.Remove(modelName);
});
}
public void LoadTexture(int address,Action<Texture> callback=null)
{
AsyncOperationHandle handle = AddressableTools.Load(address.ToString(), tex =>
{
callback(tex as Texture);
});
}
public void DisposeTexture(int address)
{
AddressableTools.Release(address.ToString());
}
private void AddHandle(string modelName,AsyncOperationHandle handleBin)
{
Queue<AsyncOperationHandle> handles;
if(!dicHandle.TryGetValue(modelName,out handles))
{
dicHandle[modelName] = new Queue<AsyncOperationHandle>();
dicHandle[modelName].Enqueue(handleBin);
}
}
private void RemovePackage(string modelName)
{
Queue<AsyncOperationHandle> handles;
if(dicHandle.TryGetValue(modelName,out handles))
{
while(handles.Count>0)
{
var v = handles.Dequeue();
AddressableTools.Release(v);
}
handles.Clear();
dicHandle.Remove(modelName);
UIPackage.RemovePackage(modelName);
}
}
public void DisposeObject(GObject obj)
{
if (obj == null) return;
int count;
string pkgId = obj.packageItem.owner.id;
if(pkgRefCountDic.TryGetValue(pkgId,out count))
{
pkgRefCountDic[pkgId] = --count;
if(count<=0)
{
var pkg = UIPackage.GetById(pkgId);
RemovePackage(pkg.name);
pkgRefCountDic.Remove(pkgId);
}
}
obj.Dispose();
}
}