关于在 MvvmCross 中何时何地使用 ObservableCollection 的建议 [英] Advice on where and when to use ObservableCollection in MvvmCross

查看:27
本文介绍了关于在 MvvmCross 中何时何地使用 ObservableCollection 的建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In an MvvmCross solution I have a singleton Service class which gets items from a web service and updates a public ObservableCollection. It does this every five seconds and items may be added or removed or their properties changed.

我还有一个 ViewModel,它有一个公共属性,该属性设置为服务的 ObservableCollection.View 绑定到 ObservableCollection,因此当添加、删除或更改项目时,视图应该更新以显示这一点.

I also have a ViewModel which has a public property which is set to the Service's ObservableCollection. The View is bound to the ObservableCollection so that when items are added, removed or changed the view should update to show this.

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

However, as expected, I am getting a threading exception because the ObservableCollection is being updated by a thread other than the Main/UI one and the binding therefore cannot update the UI.

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

Within the Service I do not have the InvokeOnMainThread call readily available so there is no obvious cross platform way to get back on to the main thread when updating the ObservableCollection. Also, doing this just seems wrong - a Service shouldn't be concerning itself with UI matters (whereas a ViewModel can).

此外,我对暴露来自服务的事件有点紧张,以防这导致 ViewModels 不被垃圾收集.我注意到在@slodge 的 N+1 系列 http://mvvmcross.wordpress.com/ 他使用的是消息服务大概是为了避免这种情况.

Also I am a bit nervous about exposing events from a Service in case this causes ViewModels to not be Garbage Collected. I note that in @slodge's N+1 series http://mvvmcross.wordpress.com/ he is using a messenging service presumably to avoid just this.

因此,一个可能的解决方案可能是发布带有最新项目列表的消息,让 ViewModel 订阅该消息并通过将消息内容与其进行比较来在 UI 线程上更新其自己的 ObservableCollection.但这似乎有点笨拙.

So a possible solution may be to publish a message with the latest list of items, and for the ViewModel to subscribe to the message and update its own ObservableCollection on the UI thread by comparing the message contents to it. But this seems a little clunky.

任何关于实现这一点的最佳方式的建议都将不胜感激 - 谢谢.

Any suggestions on the best way to implement this would be appreciated - thanks.

推荐答案

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

The original requirement that INotifyCollectionChanged must be called on the UI thread really comes from the synchronous way that the Windows controls update based upon the Added/Removed/Moved/Replaced/Reset notifications.

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

This synchronous update is, of course, entirely sensible - it would be very hard to update the UI display while another thread is actively changing it.

.Net 4.5 中有新"变化,这可能意味着未来会更好……但总的来说,这些对我来说看起来很复杂 - 请参阅 https://stackoverflow.com/a/14602121/373321

There are 'new' changes in .Net 4.5 which may mean the future is nicer... but overall these look quite complicated to me - see https://stackoverflow.com/a/14602121/373321

我所知道的处理此问题的方法与您在帖子中概述的方法基本相同:

The ways I know of to handle this are essentially the same as those outlined in your post:

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

A. keep the ObservableCollection in the Service/Model layer and marshal all events there onto the UI thread - this is possible using any class which inherits from MvxMainThreadDispatchingObject - or can be done by calling MvxMainThreadDispatcher.Instance.RequestMainThreadAction(action)

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

Whilst it's unfortunate that this means your Service/Model does have some threading knowledge, this approach can work well for the overall App experience.

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

B. make a duplicate copy of the collection in the ViewModel - updating it by some weak reference type mechanism

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

  • e.g. by sending it Messages which tell it what has been Added, Removed, Replaced or Moved (or completely Reset) - note that for this to work, then it's important that the Messages arrive in the correct order!

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

or e.g. allowing snapshots to be sent across from the Service/Model layer

选择哪一个取决于:

  • 集合更改的频率、类型和大小 - 例如无论您只是偶尔获得单行更新,还是频繁地进行大量更改,还是主要看到复杂的更改组(就 UI 而言,本质上是 Resets)
  • UI 中所需的动画级别 - 例如添加/删除的项目应该动画输入/输出吗?如果不需要动画,那么有时只需用新快照替换整个列表比计算增量更改更容易.
  • 集合本身的大小 - 显然复制大型集合会导致内存不足问题
  • 集合所需的持久性 - 如果需要持久性,则 ObservableCollection 本身可能不合适,您可能需要使用自定义的 INotifyCollectionChanged 实现(如 MyCustomList 示例)
  • the frequency, type and size of the collection changes - e.g. whether you are only getting occasional single line updates, whether you are getting frequent large bursts of changes, or whether you are mainly seeing complex groups of changes (which essentially are Resets as far as the UI is concerned)
  • the animation level required in the UI - e.g. should added/deleted items animate in/out? If no animation is required then it can sometimes be easier just to replace the entire list with a new snapshot rather than to work out the incremental changes.
  • the size of the collection itself - obviously duplicating a large collection can cause out-of-memory issues
  • the persistence required on the collection - if persistence is required, then ObservableCollection itself may not be appropriate and you may need to use a custom INotifyCollectionChanged implementation (like the MyCustomList samples)

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

I personally generally choose the (A) approach in apps - but it does depend on the situation and on the characteristics of the collection and its changes.

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

Note that while this is most definitely an mvvm issue, the underlying problem is one independent of databinding - how do you update an on-screen display of a list while the list itself is changing on a background thread?

这篇关于关于在 MvvmCross 中何时何地使用 ObservableCollection 的建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆