Skip to content

Commit

Permalink
Share the subscription to the artwork key changes so we don't create …
Browse files Browse the repository at this point in the history
…a billion subscriptions and consume more and more memory with each search
  • Loading branch information
flagbug committed Nov 8, 2014
1 parent a97121b commit 9c7878e
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 15 deletions.
22 changes: 13 additions & 9 deletions Espera.View/ViewModels/ArtistViewModel.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -12,27 +13,27 @@ namespace Espera.View.ViewModels
{
public sealed class ArtistViewModel : ReactiveObject, IComparable<ArtistViewModel>, IEquatable<ArtistViewModel>, IDisposable
{
private readonly Subject<IObservable<string>> artworkKeys;
private readonly ReactiveList<LocalSong> songs;
private readonly ObservableAsPropertyHelper<BitmapSource> cover;
private readonly int orderHint;

/// <summary>
/// The constructor.
/// </summary>
/// <param name="artistName"></param>
/// <param name="artworkKeys"></param>
/// <param name="songs"></param>
/// <param name="orderHint">
/// 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).
/// </param>
public ArtistViewModel(string artistName, IEnumerable<IObservable<string>> artworkKeys, int orderHint = 1)
public ArtistViewModel(string artistName, IEnumerable<LocalSong> songs, int orderHint = 1)
{
this.artworkKeys = new Subject<IObservable<string>>();
this.songs = new ReactiveList<LocalSong>();

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
Expand All @@ -42,7 +43,7 @@ public ArtistViewModel(string artistName, IEnumerable<IObservable<string>> 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;
Expand Down Expand Up @@ -93,11 +94,14 @@ public bool Equals(ArtistViewModel other)
return this.Name == other.Name;
}

public void UpdateArtwork(IEnumerable<IObservable<string>> keys)
public void UpdateSongs(IEnumerable<LocalSong> songs)
{
foreach (IObservable<string> 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);
}
}

Expand Down
8 changes: 2 additions & 6 deletions Espera.View/ViewModels/LocalViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,19 +166,15 @@ private void UpdateArtists()
{
ArtistViewModel model = this.allArtists.FirstOrDefault(x => x.Name.Equals(songs.Key, StringComparison.InvariantCultureIgnoreCase));

List<IObservable<string>> 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);
}
}
}
Expand Down

0 comments on commit 9c7878e

Please sign in to comment.