I am using SouceCache from DynamicData in my Xamarin Forms project to track changes from the backend. First I am getting the list of Items from backend, populate the UI and then wait for changes.
The issue is that when new(updated) object arrives from backend, I find and update it in an _innerCache collection, there is no new value emitted from observable, and UI is not updated.
Code is simplified but it is something like this:
_internalSourceCache = new SourceCache<Item, string>(o => o.Id);
public IObservable<IChangeSet<Item, string>> Connect() => _internalSourceCache.Connect();
private void OnItemUpdated(List<Item> items)
{
foreach (var item in items)
{
_internalSourceCache.Edit(innerCache =>
{
innerCache.AddOrUpdate(item);
});
}
}
And in a view model where I need those changes:
itemsService
.Connect()
.Transform(item=>
{
return new ItemCellViewModel(item);
}, (_, n) => _ = new ItemCellViewModel(n))
.Sort(SortExpressionComparer<ItemCellViewModel>.Descending(t => t.Status))
.DisposeMany()
.ObserveOn(MainThreadScheduler)
.Bind(out _items)
.Subscribe();
I am obviously missing something, but I still don't know what, so please help if you see the problem :)
There is nothing obviously wrong and all these operators are commonly used. Could it be that an exception is being thrown? To test for this you can add a Do
statement and debug or write to the console. For example:
.Do(changes => Console.WriteLine(changes), ex => Console.WriteLine(ex))
.Transform(item => new ItemCellViewModel(item))
.Do(changes => Console.WriteLine(changes), ex => Console.WriteLine(ex))
Doing this before and after each operator will allow you to narrow down the issue.
Additionally but completely unrelated to your question, never update a source like this
foreach (var item in items)
{
_internalSourceCache.Edit(innerCache =>
{
innerCache.AddOrUpdate(item);
});
}
as it is super inefficient. In this case an new change set will be emitted for every item and will be transmitted along the chain. Instead you should either do this
_internalSourceCache.Edit(innerCache =>
{
\\ doing it this way will only product a single changeset
foreach (var item in items)
innerCache.AddOrUpdate(item);
});
or if there is no logic to apply,
_internalSourceCache.AddOrUpdate(items);