ReactiveUI and DynamicData SourceCache update issue

Viewed 1346

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 :)

2 Answers

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);

I found where the problem was - that Transform method was some custom made extension method that did not perform as expected. When I referenced DynamicData Trnasform all worked like a charm! It really didn't come to my mind to F12 on Transform, but when you don't know what to do more... :) Sorry for false alarm, thanks!

Related