Files
RedHotRoast-ios/Assets/Scripts/ToolKit/GLoaderPool.cs
T

157 lines
4.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();
}
}
}