157 lines
4.5 KiB
C#
157 lines
4.5 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using FairyGUI;
|
||
|
||
namespace RedHotRoast
|
||
{
|
||
public class GLoaderPool
|
||
{
|
||
private static GLoaderPool _instance;
|
||
public static GLoaderPool Instance => _instance ??= new GLoaderPool();
|
||
|
||
private readonly Queue<GLoader> pool = new Queue<GLoader>();
|
||
private readonly LinkedList<GLoader> inUseLoaders = new LinkedList<GLoader>(); // 维护活跃顺序(LRU)
|
||
|
||
private int maxCount = 10; // 最大池子数量
|
||
private int _width = 0;
|
||
private int _height = 0;
|
||
|
||
private bool _autoDisposeTexture = true; // 是否自动释放贴图
|
||
|
||
private GLoaderPool() { }
|
||
|
||
/// <summary>
|
||
/// 初始化 Loader 池
|
||
/// </summary>
|
||
public void Init(GComponent parentObj, int maxPoolCount, int width, int height, bool autoDisposeTexture = true)
|
||
{
|
||
maxCount = maxPoolCount;
|
||
_width = width;
|
||
_height = height;
|
||
_autoDisposeTexture = autoDisposeTexture;
|
||
|
||
DisposeAll();
|
||
|
||
// 预创建 loader
|
||
for (int i = 0; i < maxCount; i++)
|
||
{
|
||
var loader = CreateLoader();
|
||
pool.Enqueue(loader);
|
||
}
|
||
}
|
||
|
||
private GLoader CreateLoader()
|
||
{
|
||
var loader = new GLoader
|
||
{
|
||
fill = FillType.ScaleMatchWidth,
|
||
align = AlignType.Center,
|
||
verticalAlign = VertAlignType.Top,
|
||
visible = false
|
||
};
|
||
loader.SetSize(_width, _height);
|
||
return loader;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从池中获取 Loader
|
||
/// </summary>
|
||
public GLoader GetLoader()
|
||
{
|
||
GLoader loader = null;
|
||
|
||
// 如果池子里有,直接取
|
||
if (pool.Count > 0)
|
||
{
|
||
loader = pool.Dequeue();
|
||
}
|
||
else if (inUseLoaders.Count >= maxCount)
|
||
{
|
||
// 如果池满了,回收最久未使用的一个(LRU)
|
||
loader = inUseLoaders.First.Value;
|
||
inUseLoaders.RemoveFirst();
|
||
RecycleLoader(loader);
|
||
Debug.Log($"[LRU回收] 回收并复用一个 Loader");
|
||
}
|
||
else
|
||
{
|
||
// 未达到上限,新建
|
||
loader = CreateLoader();
|
||
}
|
||
|
||
// 标记为使用中,放到链表末尾(最近使用)
|
||
inUseLoaders.AddLast(loader);
|
||
loader.visible = true;
|
||
return loader;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 归还 Loader
|
||
/// </summary>
|
||
public void ReturnLoader(GLoader loader)
|
||
{
|
||
if (loader == null) return;
|
||
|
||
if (inUseLoaders.Contains(loader))
|
||
{
|
||
inUseLoaders.Remove(loader);
|
||
RecycleLoader(loader);
|
||
pool.Enqueue(loader);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("尝试归还未分配的 GLoader");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回收 loader 的资源
|
||
/// </summary>
|
||
private void RecycleLoader(GLoader loader)
|
||
{
|
||
if (_autoDisposeTexture && loader.texture != null)
|
||
{
|
||
loader.texture.Dispose();
|
||
}
|
||
loader.url = null;
|
||
loader.texture = null;
|
||
loader.visible = false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新 Loader 的使用顺序(需要主动调用,避免 LRU 误判)
|
||
/// </summary>
|
||
public void TouchLoader(GLoader loader)
|
||
{
|
||
if (loader == null || !inUseLoaders.Contains(loader)) return;
|
||
inUseLoaders.Remove(loader);
|
||
inUseLoaders.AddLast(loader); // 移到链表末尾,标记为最新使用
|
||
}
|
||
|
||
public bool IsFromPool(GLoader loader)
|
||
{
|
||
return inUseLoaders.Contains(loader) || pool.Contains(loader);
|
||
}
|
||
|
||
public int GetPoolCount() => pool.Count;
|
||
public int GetInUseCount() => inUseLoaders.Count;
|
||
|
||
/// <summary>
|
||
/// 清理全部
|
||
/// </summary>
|
||
public void DisposeAll()
|
||
{
|
||
foreach (var loader in pool)
|
||
{
|
||
loader?.Dispose();
|
||
}
|
||
foreach (var loader in inUseLoaders)
|
||
{
|
||
loader?.Dispose();
|
||
}
|
||
pool.Clear();
|
||
inUseLoaders.Clear();
|
||
}
|
||
}
|
||
}
|