所有 MvvmCross 平台都要求将 UI 操作编组回 UI 线程/单元 - 但每个平台的执行方式不同......
为了解决这个问题,MvvmCross 提供了一种跨平台的方法——使用IMvxViewDispatcherProvider
注入的对象。
例如,在 WindowsPhone上IMvxViewDispatcherProvider
最终由https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxMainThreadDispatcher.cs提供MvxMainThreadDispatcher
这实现了InvokeOnMainThread
使用:
private bool InvokeOrBeginInvoke(Action action)
{
if (_uiDispatcher.CheckAccess())
action();
else
_uiDispatcher.BeginInvoke(action);
return true;
}
对于 ViewModel 中的代码:
- 你的
ViewModel
继承自MvxViewModel
- 继承
MvxViewModel
自MvxApplicationObject
- 继承
MvxApplicationObject
自MvxNotifyPropertyChanged
MvxNotifyPropertyChanged
对象继承自MvxMainThreadDispatchingObject
MvxMainThreadDispatchingObject
是https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/ViewModels/MvxMainThreadDispatchingObject.cs
public abstract class MvxMainThreadDispatchingObject
: IMvxServiceConsumer<IMvxViewDispatcherProvider>
{
protected IMvxViewDispatcher ViewDispatcher
{
get { return this.GetService().Dispatcher; }
}
protected void InvokeOnMainThread(Action action)
{
if (ViewDispatcher != null)
ViewDispatcher.RequestMainThreadAction(action);
}
}
所以...您的 ViewModel 可以调用InvokeOnMainThread(() => DoStuff());
还有一点需要注意的是,MvvmCross 自动为属性更新进行 UI 线程转换,这些属性更新通过方法在MvxViewModel
(或实际上在任何MvxNotifyPropertyChanged
对象中)发出信号RaisePropertyChanged()
- 请参阅:
protected void RaisePropertyChanged(string whichProperty)
{
// check for subscription before going multithreaded
if (PropertyChanged == null)
return;
InvokeOnMainThread(
() =>
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(whichProperty));
});
}
在https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/ViewModels/MvxNotifyPropertyChanged.cs
这种自动编组RaisePropertyChanged()
调用适用于大多数情况,但如果您从后台线程引发大量更改的属性,则可能会有点低效 - 它可能导致大量线程上下文切换。这不是您在大多数代码中需要注意的事情 - 但如果您确实发现这是一个问题,那么它可以帮助更改代码,例如:
MyProperty1 = newValue1;
MyProperty2 = newValue2;
// ...
MyProperty10 = newValue10;
到:
InvokeOnMainThread(() => {
MyProperty1 = newValue1;
MyProperty2 = newValue2;
// ...
MyProperty10 = newValue10;
});
如果您曾经使用过ObservableCollection
,请注意 MvvmCross 不会对INotifyPropertyChanged
这些类触发的or事件进行任何线程编组INotifyCollectionChanged
- 因此,作为开发人员,您可以编组这些更改。
原因:ObservableCollection
存在于 MS 和 Mono 代码库中——因此 MvvmCross 无法更改这些现有实现。