com.alicizax.unity.ui.exten.../Runtime/RecyclerView/ViewProvider/MixedViewProvider.cs

138 lines
4.4 KiB
C#
Raw Normal View History

2025-03-12 20:59:12 +08:00
using System;
using System.Collections.Generic;
using Cysharp.Text;
2025-03-12 20:59:12 +08:00
namespace AlicizaX.UI
2025-03-12 20:59:12 +08:00
{
public class MixedViewProvider : ViewProvider
{
private readonly MixedObjectPool<ViewHolder> objectPool;
private readonly Dictionary<string, int> templateIdsByName = new(StringComparer.Ordinal);
private readonly Dictionary<string, ViewHolder> templatesByName = new(StringComparer.Ordinal);
private readonly ViewHolder[] cachedTemplates;
private readonly string[] templateNames;
private readonly int[] warmCountsByType;
2025-03-12 20:59:12 +08:00
public override string PoolStats
{
get
{
#if UNITY_EDITOR || DEVELOPMENT_BUILD
return ZString.Format("hits={0}, misses={1}, destroys={2}", objectPool.HitCount, objectPool.MissCount, objectPool.DestroyCount);
#else
return string.Empty;
#endif
}
}
2025-03-12 20:59:12 +08:00
public MixedViewProvider(RecyclerView recyclerView, ViewHolder[] templates) : base(recyclerView, templates)
{
int count = 0;
for (int i = 0; i < templates.Length; i++)
{
if (templates[i] != null)
{
count++;
}
}
cachedTemplates = new ViewHolder[count];
templateNames = new string[count];
warmCountsByType = new int[count];
int typeId = 0;
for (int i = 0; i < templates.Length; i++)
2025-03-12 20:59:12 +08:00
{
ViewHolder template = templates[i];
if (template == null)
{
continue;
}
string templateName = template.GetType().Name;
templateIdsByName[templateName] = typeId;
templatesByName[templateName] = template;
cachedTemplates[typeId] = template;
templateNames[typeId] = templateName;
typeId++;
2025-03-12 20:59:12 +08:00
}
2025-05-28 19:37:38 +08:00
UnityMixedComponentFactory<ViewHolder> factory = new(templatesByName, recyclerView.Content);
2025-05-28 19:37:38 +08:00
objectPool = new MixedObjectPool<ViewHolder>(factory);
2025-03-12 20:59:12 +08:00
}
public override ViewHolder GetTemplate(string viewName)
{
if (!templatesByName.TryGetValue(viewName, out ViewHolder template))
{
#if UNITY_EDITOR || DEVELOPMENT_BUILD
UnityEngine.Debug.LogError("ViewProvider template was not found.");
#endif
return null;
}
return template;
2025-03-12 20:59:12 +08:00
}
public override ViewHolder Allocate(string viewName)
{
2025-05-28 19:37:38 +08:00
var viewHolder = objectPool.Allocate(viewName);
viewHolder.gameObject.SetActive(true);
return viewHolder;
2025-03-12 20:59:12 +08:00
}
public override void Free(string viewName, ViewHolder viewHolder)
{
2025-05-28 19:37:38 +08:00
objectPool.Free(viewName, viewHolder);
2025-03-12 20:59:12 +08:00
}
public override void Reset()
{
Clear();
(Adapter as IItemRenderCacheOwner)?.ReleaseAllItemRenders();
objectPool.ClearInactive();
2025-03-12 20:59:12 +08:00
}
public override void PreparePool()
{
int warmCount = GetRecommendedWarmCount();
if (warmCount <= 0)
{
return;
}
PrepareBucketPool(warmCount);
int itemCount = GetItemCount();
int start = Math.Max(0, LayoutManager.GetStartIndex());
int end = Math.Min(itemCount - 1, start + warmCount - 1);
Array.Clear(warmCountsByType, 0, warmCountsByType.Length);
for (int index = start; index <= end; index++)
{
string viewName = Adapter.GetViewName(index);
if (string.IsNullOrEmpty(viewName) || !templateIdsByName.TryGetValue(viewName, out int typeId))
{
continue;
}
warmCountsByType[typeId]++;
}
for (int typeId = 0; typeId < warmCountsByType.Length; typeId++)
{
int count = warmCountsByType[typeId];
if (count <= 0)
{
continue;
}
string typeName = templateNames[typeId];
int targetCount = count + Math.Max(1, LayoutManager.Unit);
objectPool.EnsureCapacity(typeName, targetCount);
objectPool.Warm(typeName, targetCount);
}
}
2025-03-12 20:59:12 +08:00
}
}