所有 MvvmCross 平台都要求将 UI 操作编组回 UI 线程/单元 - 但每个平台的执行方式不同......
为了解决这个问题,MvvmCross 提供了一种跨平台的方法 - 使用 IMvxViewDispatcherProvider 注入对象。
例如,在 WindowsPhone 上,IMvxViewDispatcherProvider 最终由 MvxMainThreadDispatcher 在 https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxMainThreadDispatcher.cs 中提供
这实现了InvokeOnMainThread 使用:
private bool InvokeOrBeginInvoke(Action action)
{
if (_uiDispatcher.CheckAccess())
action();
else
_uiDispatcher.BeginInvoke(action);
return true;
}
对于 ViewModels 中的代码:
- 您的
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 线程转换,这些属性更新通过 RaisePropertyChanged() 方法在 MvxViewModel(或实际上在任何 MvxNotifyPropertyChanged 对象中)发出信号 - 请参阅:
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 或 INotifyCollectionChanged 事件执行任何线程编组 - 所以这取决于您开发人员来整理这些更改。
原因:ObservableCollection 存在于 MS 和 Mono 代码库中 - 因此 MvvmCross 无法更改这些现有实现。