com.alicizax.unity.ui.exten.../Runtime/RecyclerView/ViewProvider/MixedViewProvider.cs
2026-04-03 10:27:02 +08:00

112 lines
3.6 KiB
C#

using System;
using System.Collections.Generic;
namespace AlicizaX.UI
{
public class MixedViewProvider : ViewProvider
{
private readonly MixedObjectPool<ViewHolder> objectPool;
private readonly Dictionary<string, ViewHolder> templatesByName = new(StringComparer.Ordinal);
public override string PoolStats =>
$"hits={objectPool.HitCount}, misses={objectPool.MissCount}, destroys={objectPool.DestroyCount}";
public MixedViewProvider(RecyclerView recyclerView, ViewHolder[] templates) : base(recyclerView, templates)
{
for (int i = 0; i < templates.Length; i++)
{
ViewHolder template = templates[i];
if (template == null)
{
continue;
}
Type templateType = template.GetType();
templatesByName[nameof(templateType)] = template;
}
UnityMixedComponentFactory<ViewHolder> factory = new(templatesByName, recyclerView.Content);
objectPool = new MixedObjectPool<ViewHolder>(factory);
}
public override ViewHolder GetTemplate(string viewName)
{
if (templates == null || templates.Length == 0)
{
throw new NullReferenceException("ViewProvider templates can not null or empty.");
}
if (!templatesByName.TryGetValue(viewName, out ViewHolder template))
{
throw new KeyNotFoundException($"ViewProvider template '{viewName}' was not found.");
}
return template;
}
public override ViewHolder[] GetTemplates()
{
if (templates == null || templates.Length == 0)
{
throw new NullReferenceException("ViewProvider templates can not null or empty.");
}
ViewHolder[] values = new ViewHolder[templatesByName.Count];
templatesByName.Values.CopyTo(values, 0);
return values;
}
public override ViewHolder Allocate(string viewName)
{
var viewHolder = objectPool.Allocate(viewName);
viewHolder.gameObject.SetActive(true);
return viewHolder;
}
public override void Free(string viewName, ViewHolder viewHolder)
{
objectPool.Free(viewName, viewHolder);
}
public override void Reset()
{
Clear();
(Adapter as IItemRenderCacheOwner)?.ReleaseAllItemRenders();
objectPool.Dispose();
}
public override void PreparePool()
{
int warmCount = GetRecommendedWarmCount();
if (warmCount <= 0)
{
return;
}
int itemCount = GetItemCount();
int start = Math.Max(0, LayoutManager.GetStartIndex());
int end = Math.Min(itemCount - 1, start + warmCount - 1);
Dictionary<string, int> counts = new(StringComparer.Ordinal);
for (int index = start; index <= end; index++)
{
string viewName = Adapter.GetViewName(index);
if (string.IsNullOrEmpty(viewName))
{
continue;
}
counts.TryGetValue(viewName, out int count);
counts[viewName] = count + 1;
}
foreach (var pair in counts)
{
int targetCount = pair.Value + Math.Max(1, LayoutManager.Unit);
objectPool.EnsureCapacity(pair.Key, targetCount);
objectPool.Warm(pair.Key, targetCount);
}
}
}
}