2026-04-22 11:13:16 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using FairyGUI;
|
|
|
|
|
|
|
2026-04-27 11:20:13 +08:00
|
|
|
|
namespace RedHotRoast
|
2026-04-22 11:13:16 +08:00
|
|
|
|
{
|
|
|
|
|
|
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();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|