使用DynamicData定期更新从API到ObservableCache的数据

时间:2019-03-04 14:57:50

标签: c# system.reactive dynamic-data reactiveui reactivex

例如,我有api来获取项目列表:

Task<ICollection<Item>> GetItemsAsync();

我想使用ObservableCache<Item, int>处理项目。

因此,我创建了IItemsService

IObservableCache<Item, int> Items { get; }

具有实现:

private IObservableCache<Items, int> _items;

public IObservableCache<Items, int> Items => _items ?? (_items = Create().AsObservableCache().Publish().RefCount());

private IObservable<IChangeSet<Items, int>> Create()
{
    return ObservableChangeSet.Create<Items, int>(cache =>
    {
        var timer = Observable.Interval(TimeSpan.FromSeconds(1))
            .SelectMany(_ => _api.GetItemsAsync())
            .Retry()
            .Subscribe(matchInfos => cache.EditDiff(matchInfos, EqualityComparer<MatchInfo>.Default));

        return timer;
    }, item => item.Id);

然后我在视图模型中使用此服务来显示项目:

_service.Connect()
    .Transform(item => new ItemViewModel(item))
    .Bind(out items)
    .Subscribe(_ => Initialized = true);

Initialized属性需要显示/隐藏加载指示器。

我有几个问题:

  1. 这是个好方法吗?
  2. 当“项目计数”为0并且Initialized属性为true时,我需要显示“没有项目”。但是,如果服务器返回0个项目-ObservableCache将不引发通知,那么Initialized属性将为false。我该怎么办?
  3. 当我处理所有订阅时,计时器不会停止。我使用RefCount(),但无济于事。

1 个答案:

答案 0 :(得分:1)

  1. 使用mutate(days = pmin(as.numeric(difftime(ResponseDate,CRMEventStartDate,units = "days")), 1)) mutate(days = as.numeric(difftime(ResponseDate,CRMEventStartDate,units = "days")), days = ifelse(days == 0, 1, days)) 是一种好方法,因为它很灵活,并且允许重试/重复逻辑。但是,ObservableChangeSet.Create在您的示例中无法使用,因为您将其应用于缓存而不是可观察到的变更集。您是否希望延迟加载缓存?如果是这样,我可以用一些例子来更新这个答案。

  2. 格伦的答案是正确的。出于优化的原因,动态数据中的空更改通知被抑制。此限制正在删除中。参见issue #206

  3. 有些单元测试涵盖了Publish().RefCount()创建的资源的处置。请参见ObservableChangeSetFixture.cs,所以我怀疑计时器没有被处置的原因是缓存本身尚未被处置并且它使订阅保持活动状态。