关于在MvvmCross中何时何地使用ObservableCollection的建议

Jas*_*ele 6 mvvm xamarin.ios mvvmcross windows-phone-8

在MvvmCross解决方案中,我有一个单件服务类,它从Web服务获取项目并更新公共ObservableCollection.它每五秒执行一次,可以添加或删除项目或更改其属性.

我还有一个ViewModel,它有一个公共属性,设置为Service的ObservableCollection.View与ObservableCollection绑定,以便在添加,删除或更改项目时,视图应更新以显示此内容.

但是,正如预期的那样,我得到了一个线程异常,因为ObservableCollection正在由Main/UI之外的线程更新,因此绑定无法更新UI.

在服务中我没有InvokeOnMainThread随时可用的调用,因此在更新ObservableCollection时没有明显的跨平台方式来返回主线程.此外,这样做似乎是错误的 - 服务不应该关注UI问题(而ViewModel可以).

另外,我有点担心从服务中暴露事件,以防这会导致ViewModel不被垃圾收集.我注意到在@ slodge的N + 1系列http://mvvmcross.wordpress.com/中,他正在使用一种消息服务,大概是为了避免这种情况.

因此,可能的解决方案可能是发布带有最新项目列表的消息,并且ViewModel可以通过比较消息内容来订阅消息并在UI线程上更新自己的ObservableCollection.但这看起来有点笨重.

任何有关实施此方法的最佳方法的建议都将受到赞赏 - 谢谢.

Stu*_*art 13

INotifyCollectionChanged必须在UI线程上调用的原始需求实际上来自Windows控制基于添加/删除/移动/替换/重置通知更新的同步方式.

当然,这种同步更新是完全合理的 - 当另一个线程正在积极地更改它时,更新UI显示将非常困难.

.Net 4.5中有"新"变化,这可能意味着未来更好......但总体而言,这看起来相当复杂 - 请参阅/sf/answers/1022148501/


我知道处理这个问题的方法与你帖子中概述的基本相同:

A.保留ObservableCollection在Service/Model层中并将那里的所有事件编组到UI线程上 - 这可以使用任何继承的类MvxMainThreadDispatchingObject- 或者可以通过调用来完成MvxMainThreadDispatcher.Instance.RequestMainThreadAction(action)

虽然不幸的是,这意味着您的服务/模型确实具有一些线程知识,但这种方法可以很好地适用于整体应用体验.

B.在ViewModel- 通过一些弱引用类型机制更新它的集合副本

  • 例如,通过发送消息告诉它添加,删除,替换或移动(或完全重置)的内容 - 请注意,为了使其正常工作,消息以正确的顺序到达非常重要!

  • 或者例如允许从服务/模型层发送快照

选择以下哪个取决于:

  • 集合变化的频率,类型和规模-例如,你是否只得到偶尔的单行更新,无论你正在变化频繁的大爆发,还是你主要是看到变化的复杂群体(基本上是Resets尽可能的UI关注)
  • 用户界面中所需的动画级别 - 例如,添加/删除的项目是否有动画输入/输出?如果不需要动画,那么有时可以更简单地用新快照替换整个列表而不是计算增量更改.
  • 集合本身的大小 - 显然重复大集合可能会导致内存不足的问题
  • 集合所需的持久性 - 如果需要持久性,那么ObservableCollection它本身可能不合适,您可能需要使用自定义INotifyCollectionChanged实现(如MyCustomList示例)

我个人通常在应用程序中选择(A)方法 - 但它确实取决于情况以及集合的特征及其变化​​.

请注意,虽然这绝对是一个mvvm问题,但潜在的问题是一个独立于数据绑定的问题 - 当列表本身在后台线程上更改时,如何更新列表的屏幕显示?