我有一个基本的Calendar / Agenda应用程序,它将列出一系列帐户和日历中的最新事件。例如,假设我有3个帐户:两个不同的Microsoft帐户和一个Google帐户。我目前将它们存储为服务(SourceCache<Account, string>
)中称为Accounts
的{{1}}。
AccountsService
是DynamicData的一部分,它基本上是Reactive Collections的一部分。我希望它具有反应性,以便在我添加或删除帐户时,应用程序中的所有内容(设置页面,日历页面等)都将自动更新。
现在,每个帐户可以有多个SourceCache<T1,T2>
。对于每个Calendar
,我想下载所有即将推出的Calendar
。问题是我需要定期执行此操作,以查看是否已添加新事件或事件是否已更改。
这是我当前的操作方式,但恐怕Rx可能真的很糟糕。
CalendarEvent
最重要的是,事件也通过订阅可观察对象来加载。那是我放置计时器的地方,它使我可以控制检查在线服务的频率。看起来像这样(20秒仅用于测试!):
var calendarSet = this.accountsService.Accounts.Connect()
.ObserveOn(RxApp.TaskpoolScheduler)
.TransformMany(x =>
{
ReadOnlyObservableCollection<Models.Calendar> subCalendars;
x.CalendarService.Calendars.Connect()
.AutoRefreshOnObservable(calendar => calendar.IsEnabledChanged)
.AutoRefreshOnObservable(calendar => calendar.IsColorChanged)
.Filter(calendar=>calendar.IsEnabled)
.Bind(out subCalendars)
.Subscribe();
return subCalendars;
}, x => x.CacheKey)
.ObserveOnDispatcher()
.Publish();
calendarSet
.Bind(out calendars)
.Subscribe();
var eventSet = calendarSet
.ObserveOn(RxApp.TaskpoolScheduler)
.Transform( calendar =>
{
var events = new List<Models.CalendarEvent>();
Debug.WriteLine(calendar.Name);
calendar.CalendarService.CalendarEventsObservable(calendar).Subscribe(items =>
{
events.AddRange(items);
});
return events;
})
.TransformMany(x => x, x => x.Key)
.Filter(x => x.EndDateTime > DateTimeOffset.Now)
.Sort(new Models.CalendarEventSorter())
.ObserveOnDispatcher()
.Bind(out calendarEvents)
.Subscribe();
calendarSet.Connect();
这似乎有效!我可以启用/禁用某些日历,事件将在绑定列表中显示或消失。我可以看到事件每隔一定的时间就会更新……并且我假设由于我使用的TransformMany的密钥与public IObservable<List<Models.CalendarEvent>> CalendarEventsObservable(Models.Calendar calendar)
{
var obs = Observable.Interval(TimeSpan.FromSeconds(20)).SelectMany(async x =>
{
var items = await GetAllEventsForCalendarAsync(calendar);
return items;
});
return obs;
}
的在线ID(已固定)相关联,因此新下载的事件仅替换了缓存中的旧文件。我在用户界面上看不到任何闪烁。
**更正:似乎是因为我不小心从另一个试验中遗留下来的骇客而起作用。在原始帐户SourceCache上,我正在运行一个调用Accounts.Refresh()的计时器。如果我将其取出,将无济于事。
这是正确的方法吗?拜托,请赐教...我在Rx和DynamicData方面有点挣扎。有很多操作员,我还不知道该怎么办。
谢谢!
答案 0 :(得分:2)
您似乎已经回答了自己的问题,并且代码看起来比原始代码更优化。但是我建议可以进行优化:
使用AutoRefreshOnObservable,这将使您可以创建单个可观察对象,而不是两次使用AutoRefresh。
我无法从代码中判断CalendarEventsObservable是返回单个值还是集合。如果它返回一个集合,则可以使用EditDiff代替使用AddOrUpdate。 EditDiff期望比较指定的相等性,并防止触发不必要的通知。
答案 1 :(得分:0)
我已经重写了一些代码,它似乎工作得更好。即使没有黑客,我也可以在原始Refresh()
Account
上手动调用SourceCache
。
我意识到我一直在滥用Publish方法。另外,在transform语句中订阅可观察对象将不会起作用,因为它不是DynamicData可观察对象(具有变更集)。相反,我决定做一个SubscribeMany来订阅来自每个CalendarEventObservable
的所有Calendar
,在订阅的Action逻辑中,我将填充SourceCache
中的新CalendarEvent
s。没有事件会被删除,但是由于缓存键的存在,重复的事件只会覆盖旧的事件,而且我可以从未选择的日历中过滤掉事件。
private SourceCache<Models.CalendarEvent, string> calendarEventCache;
public IObservableCache<Models.CalendarEvent, string> CalendarEventCache => calendarEventCache.Connect().AutoRefreshOnObservable(x=>x.Parent.IsEnabledChanged).Filter(x=>x.Parent.IsEnabled).AsObservableCache();
//////////////////
///IN CONSTRUCTOR:
calendarEventCache = new SourceCache<Models.CalendarEvent, string>(x => x.Key);
calendarsCache = this.accountsService.Accounts.Connect()
.ObserveOn(RxApp.TaskpoolScheduler)
.TransformMany(x =>
{
ReadOnlyObservableCollection<Models.Calendar> subCalendars;
x.CalendarService.Calendars.Connect()
.AutoRefreshOnObservable(calendar => calendar.IsEnabledChanged)
.AutoRefreshOnObservable(calendar => calendar.IsColorChanged)
.Filter(calendar => calendar.IsEnabled)
.Bind(out subCalendars)
.Subscribe();
return subCalendars;
}, x => x.CacheKey)
.ObserveOnDispatcher()
.AsObservableCache();
calendarsCache.Connect()
.ObserveOn(RxApp.TaskpoolScheduler)
.SubscribeMany(calendar =>
{
return calendar.CalendarService.CalendarEventsObservable(calendar).Subscribe(calendarEvent =>
{
calendarEventCache.AddOrUpdate(calendarEvent);
});
})
.Subscribe();
现在,在UI的视图模型中,我订阅了SourceCache<CalendarEvent,string>
;