From 9c7878e997666a1009c16b0ff722f14233c57c1d Mon Sep 17 00:00:00 2001 From: Dennis Daume Date: Sat, 8 Nov 2014 20:03:45 +0100 Subject: [PATCH] Share the subscription to the artwork key changes so we don't create a billion subscriptions and consume more and more memory with each search --- Espera.View/ViewModels/ArtistViewModel.cs | 22 +++++++++++++--------- Espera.View/ViewModels/LocalViewModel.cs | 8 ++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Espera.View/ViewModels/ArtistViewModel.cs b/Espera.View/ViewModels/ArtistViewModel.cs index e5200e21..7771bc2f 100644 --- a/Espera.View/ViewModels/ArtistViewModel.cs +++ b/Espera.View/ViewModels/ArtistViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Threading.Tasks; @@ -12,7 +13,7 @@ namespace Espera.View.ViewModels { public sealed class ArtistViewModel : ReactiveObject, IComparable, IEquatable, IDisposable { - private readonly Subject> artworkKeys; + private readonly ReactiveList songs; private readonly ObservableAsPropertyHelper cover; private readonly int orderHint; @@ -20,19 +21,19 @@ public sealed class ArtistViewModel : ReactiveObject, IComparable /// - /// + /// /// /// A hint that tells this instance which position it has in the artist list. This helps for /// priorizing the album cover loading. The higher the number, the earlier it is in the list /// (Think of a reversed sorted list). /// - public ArtistViewModel(string artistName, IEnumerable> artworkKeys, int orderHint = 1) + public ArtistViewModel(string artistName, IEnumerable songs, int orderHint = 1) { - this.artworkKeys = new Subject>(); + this.songs = new ReactiveList(); this.orderHint = orderHint; - this.cover = this.artworkKeys + this.cover = this.songs.ItemsAdded.Select(x => x.WhenAnyValue(y => y.ArtworkKey)) .Merge() .Where(x => x != null) .Distinct() // Ignore duplicate artworks @@ -42,7 +43,7 @@ public ArtistViewModel(string artistName, IEnumerable> artwo .ToProperty(this, x => x.Cover); var connect = this.Cover; // Connect the property to the source observable immediately - this.UpdateArtwork(artworkKeys); + this.UpdateSongs(songs); this.Name = artistName; this.IsAllArtists = false; @@ -93,11 +94,14 @@ public bool Equals(ArtistViewModel other) return this.Name == other.Name; } - public void UpdateArtwork(IEnumerable> keys) + public void UpdateSongs(IEnumerable songs) { - foreach (IObservable key in keys) + var songsToAdd = songs.Where(x => !this.songs.Contains(x)).ToList(); + + // Can't use AddRange here, ReactiveList resets the list on big changes and we don't get the add notification + foreach (LocalSong song in songsToAdd) { - this.artworkKeys.OnNext(key); + this.songs.Add(song); } } diff --git a/Espera.View/ViewModels/LocalViewModel.cs b/Espera.View/ViewModels/LocalViewModel.cs index bc184209..c8c5174b 100644 --- a/Espera.View/ViewModels/LocalViewModel.cs +++ b/Espera.View/ViewModels/LocalViewModel.cs @@ -166,19 +166,15 @@ private void UpdateArtists() { ArtistViewModel model = this.allArtists.FirstOrDefault(x => x.Name.Equals(songs.Key, StringComparison.InvariantCultureIgnoreCase)); - List> artworkKeys = songs - .Select(x => x.WhenAnyValue(y => y.ArtworkKey)) - .ToList(); - if (model == null) { int priority = orderedArtists.IndexOf(songs.Key) + 1; - this.allArtists.Add(new ArtistViewModel(songs.Key, artworkKeys, priority)); + this.allArtists.Add(new ArtistViewModel(songs.Key, songs, priority)); } else { - model.UpdateArtwork(artworkKeys); + model.UpdateSongs(songs); } } }