private void ApplyPendingChanges() { try { List <NotifyCollectionChangedEventArgs> allEventArgs = new List <NotifyCollectionChangedEventArgs>(); this.Log().Debug("Beginning update"); adapter.PerformBatchUpdates(() => { if (this.Log().Level >= LogLevel.Debug) { this.Log().Debug("The pending changes (in order received) are:"); foreach (var pendingChange in pendingChanges) { this.Log().Debug( "Section {0}: Action={1}, OldStartingIndex={2}, NewStartingIndex={3}, OldItems.Count={4}, NewItems.Count={5}", pendingChange.Item1, pendingChange.Item2.Action, pendingChange.Item2.OldStartingIndex, pendingChange.Item2.NewStartingIndex, pendingChange.Item2.OldItems == null ? "null" : pendingChange.Item2.OldItems.Count.ToString(), pendingChange.Item2.NewItems == null ? "null" : pendingChange.Item2.NewItems.Count.ToString()); } } foreach (var sectionedUpdates in pendingChanges.GroupBy(x => x.Item1)) { var section = sectionedUpdates.First().Item1; this.Log().Debug("Processing updates for section {0}", section); var allSectionEas = sectionedUpdates .Select(x => x.Item2) .ToList(); if (allSectionEas.Any(x => x.Action == NotifyCollectionChangedAction.Reset)) { this.Log().Debug("Section {0} included a reset notification, so reloading that section.", section); #if UNIFIED adapter.ReloadSections(new NSIndexSet((nuint)section)); #else adapter.ReloadSections(new NSIndexSet((uint)section)); #endif continue; } var updates = allSectionEas .SelectMany(GetUpdatesForEvent) .ToList(); if (this.Log().Level >= LogLevel.Debug) { this.Log().Debug( "Updates for section {0}: {1}", section, updates .Aggregate( new StringBuilder(), (current, next) => { if (current.Length > 0) { current.Append(":"); } return(current.Append(next)); }, x => x.ToString())); } var normalizedUpdates = IndexNormalizer.Normalize(updates); if (this.Log().Level >= LogLevel.Debug) { this.Log().Debug( "Normalized updates for section {0}: {1}", section, normalizedUpdates .Aggregate( new StringBuilder(), (current, next) => { if (current.Length > 0) { current.Append(":"); } return(current.Append(next)); }, x => x.ToString())); } foreach (var normalizedUpdate in normalizedUpdates) { switch (normalizedUpdate.Type) { case UpdateType.Add: DoUpdate(adapter.InsertItems, new[] { normalizedUpdate.Index }, section); break; case UpdateType.Delete: DoUpdate(adapter.DeleteItems, new[] { normalizedUpdate.Index }, section); break; default: throw new NotSupportedException(); } } } }, () => { this.Log().Debug("Ending update"); didPerformUpdates.OnNext(allEventArgs); }); } finally { pendingChanges.Clear(); isCollectingChanges = false; } }
private void ApplyPendingChanges(int sectionInfoId) { Debug.Assert(Thread.CurrentThread.ManagedThreadId == this.mainThreadId); Debug.Assert(this.isCollectingChanges); this.Log().Debug("[#{0}] Applying pending changes", sectionInfoId); try { adapter.PerformUpdates( () => { if (this.IsDebugEnabled) { this.Log().Debug("[#{0}] The pending changes (in order received) are:", sectionInfoId); foreach (var pendingChange in pendingChanges) { this.Log().Debug( "[#{0}] Section {1}: Action = {2}, OldStartingIndex = {3}, NewStartingIndex = {4}, OldItems.Count = {5}, NewItems.Count = {6}", sectionInfoId, pendingChange.Item1, pendingChange.Item2.Action, pendingChange.Item2.OldStartingIndex, pendingChange.Item2.NewStartingIndex, pendingChange.Item2.OldItems == null ? "null" : pendingChange.Item2.OldItems.Count.ToString(), pendingChange.Item2.NewItems == null ? "null" : pendingChange.Item2.NewItems.Count.ToString()); } } foreach (var sectionedUpdates in pendingChanges.GroupBy(x => x.Item1)) { var section = sectionedUpdates.First().Item1; this.Log().Debug("[#{0}] Processing updates for section {1}", sectionInfoId, section); var allSectionChanges = sectionedUpdates .Select(x => x.Item2) .ToList(); if (allSectionChanges.Any(x => x.Action == NotifyCollectionChangedAction.Reset)) { this.Log().Debug("[#{0}] Section {1} included a reset notification, so reloading that section.", sectionInfoId, section); adapter.ReloadSections(new NSIndexSet((nuint)section)); continue; } var updates = allSectionChanges .SelectMany(GetUpdatesForEvent) .ToList(); var normalizedUpdates = IndexNormalizer.Normalize(updates); if (this.IsDebugEnabled) { this.Log().Debug( "[#{0}] Updates for section {1}: {2}", sectionInfoId, section, string.Join(":", updates)); this.Log().Debug( "[#{0}] Normalized updates for section {1}: {2}", sectionInfoId, section, string.Join(":", normalizedUpdates)); } foreach (var normalizedUpdate in normalizedUpdates) { switch (normalizedUpdate.Type) { case UpdateType.Add: DoUpdate(adapter.InsertItems, new[] { normalizedUpdate.Index }, section); break; case UpdateType.Delete: DoUpdate(adapter.DeleteItems, new[] { normalizedUpdate.Index }, section); break; default: throw new NotSupportedException(); } } } }, () => this.Log().Debug("[#{0}] Pending changes applied", sectionInfoId)); } finally { pendingChanges.Clear(); } }