我正在使用MvvmCross
框架构建跨平台移动应用程序。
由于我想在ViewModel之间共享信息,我使用内置的MvxMessenger
在ViewModel的构造函数中注册通知。
让我们假设一条名为ShowAdsMsg
的消息,然后ViewModel看起来如下:
public class AdsViewModel : BaseLookersViewModel, IAdsViewModel
{
private MvxSubscriptionToken _showAdsMsgToken;
public AdsViewModel()
{
_showAdsMsgToken = MvxMessenger.Subscribe<ShowAdsMsg>(message => onShowAdsNavigation(), MvxReference.Weak);
MyMessenger.PublishLastMessage();
}
private void onShowAdsNavigation()
{
//Do Stuff
}
}
关于MyMessenger
事情:
ViewModel的实际导航是从MainViewModel
执行的。
由于在导航本身的那一刻,AdsViewModel
尚不存在,因此MainViewModel
发布的消息无法到达。
所以,我的想法是天真地“记住”消息并在新的ViewModel准备就绪时发布它
所以现在来自MainViewModel
的导航调用看起来像是:
private void navigate()
{
MyMessenger.RememberMessage(new ShowAdsMsg(this));
ShowViewModel<AdsViewModel>( );
}
我现在可以导航到ViewModel,并且所有通知都已成功捕获。
然而......
当我按下设备上的BACK按钮并重新导航到相同的ViewModel时,
正在再次调用构造函数,因此重新发生消息订阅。
因此,当消息到达时,onShowAdsNavigation()
处理程序被触发两次!
我发现了this类似的帖子,讨论了如何正确处理ViewModel的问题,
但它不能直接解决我的问题。
我需要的是一个解决方案。它可以是以下任何一种:
先谢谢你的帮助!
编辑: 我找到this SO答案,它基本上回答了上面列表中的第3项。 不过,我想知道我应该采取什么方法处理信使问题。
另一个编辑: 我验证了MvvmCross教程N-05-MultiPage存在相同的行为。我只是向SecondViewModel添加了一个ctor,并且在每次BACK + Renavigate之后我在它内部打了一个断点。
答案 0 :(得分:2)
解释为什么再次调用构造函数,以及如何避免这种情况。
ctor
未在同一对象上调用两次 - 而是每次都会创建一个新的View
和一个新的ViewModel
。
默认情况下, 期望在每个平台上的每个转发导航中创建新的ViewModel。
默认情况下,我不会期望在WindowsPhone上的后退按钮期间发生这种情况 - 这在我的测试用例中不会发生 - 但如果出现这种情况可能会发生:
在没有看到更多代码的情况下,我无法再猜测为什么会发生这种情况。
我个人建议你深入了解为什么你会看到在Back期间创建新的ViewModel,但是如果你只想快速修复,那么你可以看看覆盖MvvmCross中的ViewModelLocator - 参见MvvmCross: Does ShowViewModel always construct new instances?
请注意,在WindowsStore上,我希望会发生这种情况 - 默认情况下,WindowsStore不会从内存中的Backstack中保存Pages - 但如果需要,可以通过设置NavigationCacheMode = NavigationCacheMode.Enabled;
来覆盖此页面。