private void NotifyViewRecycled(UnoViewHolder holder) { if (_onRecycled.TryGetValue(holder, out var actions)) { actions.ForEach(a => a()); _onRecycled.Remove(holder); } }
/// <summary> /// Queues an action to be executed when the provided viewHolder is being recycled. /// </summary> internal void OnRecycled(UnoViewHolder unoViewHolder, Action action) { if (!_onRecycled.TryGetValue(unoViewHolder, out var actions)) { _onRecycled[unoViewHolder] = actions = new List <Action>(); } actions.Add(action); }
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) { if (viewType != HeaderItemType && viewType != FooterItemType) { var pool = Owner.GetRecycledViewPool(); pool.SetMaxRecycledViews(viewType, MaxRecycledViewsPerViewType); } if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) { this.Log().Debug($"Creating view with view type {viewType}."); } var container = GenerateContainer(viewType); var holder = new UnoViewHolder(container); FrameworkElement.InitializePhaseBinding(holder.ItemView as ContentControl); return(holder); }
public override View GetViewForPositionAndType(RecyclerView.Recycler recycler, int position, int type) { UnoViewHolder result = null; List <UnoViewHolder> views; if (!_cachedViews.TryGetValue(type, out views)) { return(null); } //Remove views that are animating out views.RemoveAll(IsItemUnrecyclable); foreach (var holder in views) { //Look for an exact match if (holder.LayoutPosition == position) { result = holder; views.Remove(result); break; } } if (result == null && views.Count > 0) { //Get any match of correct type result = views[views.Count - 1]; views.RemoveAt(views.Count - 1); } if (result != null) { Layout.AttachView(result.ItemView); recycler.BindViewToPosition(result.ItemView, position); if (this.Log().IsEnabled(Uno.Foundation.Logging.LogLevel.Debug)) { this.Log().Debug($"Returning cached view for position={position} and view type={type}. {views.Count} cached views remaining."); } return(result.ItemView); } return(null); }
public ElementViewRecord(int displayPosition, UnoViewHolder viewHolder) { DisplayPosition = displayPosition; ViewHolder = viewHolder; IsEmpty = false; }
/// <summary> /// Retrieve view for <paramref name="displayPosition"/> from intermediate cache. /// </summary> private View GetViewFromIntermediateCache(RecyclerView.Recycler recycler, int displayPosition) { if (_shouldBlockIntermediateCache) { return(null); } UnoViewHolder result = null; List <UnoViewHolder> views; var type = _owner.CurrentAdapter.GetItemViewType(displayPosition); if (!_intermediateCache.TryGetValue(type, out views)) { return(null); } //Remove views that are animating out views.RemoveAll(RemoveUnrecyclable); foreach (var holder in views) { //Look for an exact match if (holder.LayoutPosition == displayPosition) { result = holder; views.Remove(result); _owner.CurrentAdapter.RegisterPhaseBinding(result); //Restart phase binding, since this won't be rebound by adapter break; } } if (result == null && views.Count > 0) { // Get any match of correct type except views that could be reused without rebinding for (int i = views.Count - 1; i >= 0; i--) { var view = views[i]; if (!IsInTargetRange(view.LayoutPosition)) { result = view; views.RemoveAt(i); break; } } } if (result != null) { recycler.BindViewToPosition(result.ItemView, displayPosition); if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) { this.Log().Debug($"Returning cached view for position={displayPosition} and view type={type}. {views.Count} cached views remaining."); } return(result.ItemView); } return(null); bool RemoveUnrecyclable(UnoViewHolder holderInner) { var isUnrecyclable = !holderInner.IsRecyclable; if (isUnrecyclable) { Layout.RemoveAndRecycleView(holderInner.ItemView, recycler); } return(isUnrecyclable); } }
private static bool IsItemUnrecyclable(UnoViewHolder obj) { return(!obj.IsRecyclable); }
private void RecycleView(RecyclerView.Recycler recycler, UnoViewHolder holder) { Layout.RemoveDetachedView(holder.ItemView); recycler.RecycleView(holder.ItemView); }