MvvmCross ViewModel缓存和重新初始化

Kla*_*Nji 5 viewmodel viewmodellocator mvvmcross

我需要能够拦截框架并在从缓存重新加载ViewModel时执行重新初始化.由于没有重新创建ViewModel,我既不能使用Init(),MvxViewModel.InitFromBundle,也不能使用MvxViewModel.ReloadFromBundle方法.

我正在尝试调试一种情况,单击后退按钮可以恢复状态不一致的ViewModel.某种MvxViewModel.OnReloading()会有所帮助.

有没有办法在v3中这样做?

编辑:

假设我有FirstPageViewModel,它公开了一个导航到SecondPageViewModel的命令.根据我观察的内容,如果在SecondPageView上单击模拟器的后退按钮,则不会构造FirstPageViewModel.相反,我相信它会从某个缓存中检索,然后绑定到View.此缓存可能是IMvxSingleViewModel缓存的实现.

因此,ViewModel构造之后的常规流(在此方案中调用Init(),InitFromBundle()和ReloadFromBundle()不适用.换句话说,我需要一种方法来重新初始化ViewModel,无论它是刚刚构建还是从缓存中复活.如果是前者,我可以使用Init()方法.如果后者为真,则无法在ViewModel本身内执行此操作.

这就是问题:

我有一个ICollectionService实例,它从FirstViewModel传递给SecondViewModel.FirstView还包含一个绑定到此CollectionService的ListView.因为CollectionService没有强类型,所以我可以传递它并使用适当的项模板在视图中呈现其项目.

在显示SecondViewModel之前,FirstViewModel检索一些远程数据并填充CollectionService.显示SecondViewModel时,其视图使用不同的项模板显示CollectionService中的数据.但是,如果我导航回来,由于FirstViewModel仍然引用CollectionService,FirstView将呈现SecondViewModel使用的数据,除非可以重新初始化FirstViewModel,清除过程中的CollectionService.也许这种方法是错误的,但这是我的问题的症结所在.

我不知道平台是否有所作为,因为我预计Windows Phone和iOS上会出现相同的行为,因为这种重新初始化将在Core模块中进行.尽管如此,这些都是对Android的观察.

TIA.

Stu*_*art 5

感谢您更新问题以提供更多信息.

使用MvvmCross方法进行跨平台开发使您可以利用本机UI平台.这确实意味着您 - 开发人员 - 确实需要了解这些平台 - 并且要理解的关键事项之一是"视图"生命周期,包括在导航堆栈中使用时.

默认情况下,MvvmCross不会在任何相当长的时间内缓存视图模型.在屏幕转换(例如旋转)期间偶尔会出现短暂的缓存,但不存在长期缓存.相反,当创建一个新视图时,默认情况下mvx创建一个新的视图模型来与它一起使用 - 并且该对保持在一起"终身" - 生命的结束由视图决定.

我建议您花些时间阅读每个平台上的基本生命周期和导航范例.

  • 在iOS上这意味着特别了解UiNavigationController,它在内存中维护一堆UiViewControllers(每个都将在mvx中与一个单独的viewmodel结合)

  • WindowsPhone中的情况类似于RootFrame在RAM中维护一堆页面.这里有一个复杂的问题 - 墓碑 - 但是在你获得基本生命周期之后才会忘记它.

  • 在Android上,情况类似,但略有不同.对于基本应用程序,您可以假设Android将在应用程序的生命周期内在RAM中维护一堆活动页面.然而,Android实际上要复杂得多 - 操作系统在决定回收内存时可以从RAM中删除背堆物品.在这些情况下,有时会出现一些"墓碑形"和脱水现象 - 但是,我再次建议你忽略这一点,直到你掌握了基础知识.

  • 在winrt上,默认情况下,情况实际上就是你在描述中理解的情况 - backstack只保存状态信息 - 视图本身不会缓存在RAM中.

上面的故事希望能让您对每个平台上的导航堆栈中的视图生命周期有所了解 - 因此也为您提供了视图模型生命周期.


现在,如果您希望视图模型(或其他一些应用程序级别对象)知道视图可见性状态,那么您需要拦截每个平台上的一些视图事件并将这些事件传递给视图楷模.

例如,您的FirstViewModel可以将OnMadeVisible()公开为自定义Api.在这种情况下,您可以确保在Windows上调用OnNavigatedTo,在Android上调用OnResume,在iOS上调用ViewDidAppear


或者,如果您正在查看ViewModel-ViewModel通信的一般机制,那么我建议您查看类似的内容


注意:

显然,导航堆栈并不是唯一的导航范例 - 如果您的应用程序也使用弹出窗口,标签,拆分视图,汉堡包等,那么您还需要了解这些视图生命周期.

如果您对View生命周期有疑问,那么向其构造函数和关键生命周期事件添加跟踪是一个很好的第一步,


最后需要注意的是,如果你决定默认的viewmodel位置和viewmodel生命周期不是你的应用所需要的 - 例如,如果你想使用单例视图模型,那么这很容易实现 - 看看覆盖app.cs中的视图模型定位器类.