11
This commit is contained in:
parent
6f897a7af7
commit
6ceaa2509b
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
@ -8,12 +9,30 @@ namespace AlicizaX.UI
|
||||
{
|
||||
private float[] itemLengths = Array.Empty<float>();
|
||||
private float[] itemPositions = Array.Empty<float>();
|
||||
private int rentedArraySize = 0;
|
||||
private Vector2 firstItemSize = Vector2.zero;
|
||||
private int cachedItemCount = -1;
|
||||
private bool positionCacheDirty = true;
|
||||
|
||||
public MixedLayoutManager() { }
|
||||
|
||||
~MixedLayoutManager()
|
||||
{
|
||||
ReturnRentedArrays();
|
||||
}
|
||||
|
||||
private void ReturnRentedArrays()
|
||||
{
|
||||
if (rentedArraySize > 0)
|
||||
{
|
||||
ArrayPool<float>.Shared.Return(itemLengths);
|
||||
ArrayPool<float>.Shared.Return(itemPositions);
|
||||
itemLengths = Array.Empty<float>();
|
||||
itemPositions = Array.Empty<float>();
|
||||
rentedArraySize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override Vector2 CalculateContentSize()
|
||||
{
|
||||
positionCacheDirty = true;
|
||||
@ -144,10 +163,18 @@ namespace AlicizaX.UI
|
||||
|
||||
private void RebuildPositionCache(int itemCount)
|
||||
{
|
||||
if (itemLengths.Length != itemCount)
|
||||
// ArrayPool.Rent 返回的数组长度 >= 请求长度,rentedArraySize 记录实际容量。
|
||||
// 仅当 itemCount 超出当前容量时才归还并重新租用,缩容时复用原数组。
|
||||
if (itemCount > rentedArraySize)
|
||||
{
|
||||
itemLengths = itemCount > 0 ? new float[itemCount] : Array.Empty<float>();
|
||||
itemPositions = itemCount > 0 ? new float[itemCount] : Array.Empty<float>();
|
||||
ReturnRentedArrays();
|
||||
|
||||
if (itemCount > 0)
|
||||
{
|
||||
itemLengths = ArrayPool<float>.Shared.Rent(itemCount);
|
||||
itemPositions = ArrayPool<float>.Shared.Rent(itemCount);
|
||||
rentedArraySize = itemLengths.Length;
|
||||
}
|
||||
}
|
||||
|
||||
firstItemSize = itemCount > 0 ? viewProvider.CalculateViewSize(0) : Vector2.zero;
|
||||
|
||||
@ -188,9 +188,12 @@ namespace AlicizaX.UI
|
||||
|
||||
private void TrackAllocate(string typeName)
|
||||
{
|
||||
int active = GetActiveCount(typeName) + 1;
|
||||
activeCountByType.TryGetValue(typeName, out int active);
|
||||
active++;
|
||||
activeCountByType[typeName] = active;
|
||||
if (active > GetPeakActiveCount(typeName))
|
||||
|
||||
peakActiveByType.TryGetValue(typeName, out int peak);
|
||||
if (active > peak)
|
||||
{
|
||||
peakActiveByType[typeName] = active;
|
||||
}
|
||||
@ -198,14 +201,21 @@ namespace AlicizaX.UI
|
||||
|
||||
private void TrackFree(string typeName)
|
||||
{
|
||||
int active = GetActiveCount(typeName);
|
||||
activeCountByType.TryGetValue(typeName, out int active);
|
||||
if (active > 0)
|
||||
{
|
||||
activeCountByType[typeName] = active - 1;
|
||||
}
|
||||
|
||||
int recommendedMax = GetPeakActiveCount(typeName) + 1;
|
||||
if (recommendedMax > GetMaxSize(typeName))
|
||||
peakActiveByType.TryGetValue(typeName, out int peak);
|
||||
int recommendedMax = peak + 1;
|
||||
typeSize.TryGetValue(typeName, out int currentMax);
|
||||
if (currentMax <= 0)
|
||||
{
|
||||
currentMax = defaultMaxSizePerType;
|
||||
}
|
||||
|
||||
if (recommendedMax > currentMax)
|
||||
{
|
||||
typeSize[typeName] = recommendedMax;
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ namespace AlicizaX.UI
|
||||
{
|
||||
private readonly MixedObjectPool<ViewHolder> objectPool;
|
||||
private readonly Dictionary<string, ViewHolder> templatesByName = new(StringComparer.Ordinal);
|
||||
private readonly Dictionary<string, int> warmCounts = new(StringComparer.Ordinal);
|
||||
|
||||
public override string PoolStats =>
|
||||
$"hits={objectPool.HitCount}, misses={objectPool.MissCount}, destroys={objectPool.DestroyCount}";
|
||||
@ -85,8 +86,8 @@ namespace AlicizaX.UI
|
||||
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);
|
||||
|
||||
warmCounts.Clear();
|
||||
for (int index = start; index <= end; index++)
|
||||
{
|
||||
string viewName = Adapter.GetViewName(index);
|
||||
@ -95,11 +96,11 @@ namespace AlicizaX.UI
|
||||
continue;
|
||||
}
|
||||
|
||||
counts.TryGetValue(viewName, out int count);
|
||||
counts[viewName] = count + 1;
|
||||
warmCounts.TryGetValue(viewName, out int count);
|
||||
warmCounts[viewName] = count + 1;
|
||||
}
|
||||
|
||||
foreach (var pair in counts)
|
||||
foreach (var pair in warmCounts)
|
||||
{
|
||||
int targetCount = pair.Value + Math.Max(1, LayoutManager.Unit);
|
||||
objectPool.EnsureCapacity(pair.Key, targetCount);
|
||||
|
||||
@ -177,7 +177,7 @@ namespace AlicizaX.UI
|
||||
|
||||
if (!viewHoldersByDataIndex.TryGetValue(viewHolder.DataIndex, out List<ViewHolder> holders))
|
||||
{
|
||||
holders = new List<ViewHolder>();
|
||||
holders = new List<ViewHolder>(1);
|
||||
viewHoldersByDataIndex[viewHolder.DataIndex] = holders;
|
||||
}
|
||||
|
||||
@ -199,7 +199,14 @@ namespace AlicizaX.UI
|
||||
return;
|
||||
}
|
||||
|
||||
holders.Remove(viewHolder);
|
||||
// 用末尾元素覆盖目标项再移除末位,避免 List.Remove 的线性搜索+内存搬移。
|
||||
int idx = holders.LastIndexOf(viewHolder);
|
||||
if (idx >= 0)
|
||||
{
|
||||
holders[idx] = holders[holders.Count - 1];
|
||||
holders.RemoveAt(holders.Count - 1);
|
||||
}
|
||||
|
||||
if (holders.Count == 0)
|
||||
{
|
||||
viewHoldersByDataIndex.Remove(viewHolder.DataIndex);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user