MvvmCross ViewModel缓存并重新初始化 [英] MvvmCross ViewModel caching and re-initializing

查看:134
本文介绍了MvvmCross ViewModel缓存并重新初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to be able to intercept the framework and perform so re-initialization when a ViewModel is being reloaded from the cache. Since the ViewModel is not being recreated, I can neither use the Init(), MvxViewModel.InitFromBundle, nor MvxViewModel.ReloadFromBundle methods.

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

I am trying to debug a situation where clicking on the back button restores a ViewModel with inconsistent state. Some sort of MvxViewModel.OnReloading() would help.

在v3中有没有办法做到这一点?

Is there a way to do this in v3?

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

Assume I have FirstPageViewModel which exposes a command to navigate to SecondPageViewModel. Based on what I am observing, if you click on the back button of the simulator while on the SecondPageView, FirstPageViewModel is not constructed. Instead, it is retrieved, I believe, from some cache, then bound to the View. This cache is possibly an implementation of IMvxSingleViewModel cache.

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

Thus, the regular flow after ViewModel construction, where you call Init(), InitFromBundle() and ReloadFromBundle() does not apply in this scenario. In other words, I need a way to re-initialize a ViewModel regardless of whether it was just newly constructed, or it being resurrected from a cache. If the former, I can use an Init() method. If the latter is true, there is no way to do this within the ViewModel itself.

这是问题所在

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

I have an instance of ICollectionService which is passed from FirstViewModel to SecondViewModel. FirstView also contains a ListView that is bound to this CollectionService. Because CollectionService is not strongly typed I can pass it around and use the appropriate item template to render its items in the view.

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

Before showing SecondViewModel, FirstViewModel retrieves some remote data and populates the CollectionService. When SecondViewModel is shown, its view displays data from the CollectionService using a different item template. However, if I navigate back, since FirstViewModel is still referencing the CollectionService, FirstView will render data that was used by SecondViewModel unless FirstViewModel could be re-initialized, clearing the CollectionService in the process. Maybe the approach is wrong but this is the crux of my problem.

我不知道该平台是否有所作为,因为我希望Windows Phone和iOS上的行为相同,因为在Core模块中会发生这种重新初始化.尽管如此,这些是在Android上的观察结果.

I do not know if the platform makes a difference, as I would expect the same behavior on Windows Phone and iOS as this re-initialization will occur in the Core module. Nonetheless these are observations on Android.

TIA.

推荐答案

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

Thanks for updating your question to provide much more information.

使用MvvmCross方法进行跨平台开发使您可以利用本机UI平台.这确实意味着您(开发人员)确实需要学习一些有关这些平台的知识,而要理解的关键之一就是视图"生命周期,包括在导航堆栈中的使用时间.

Using the MvvmCross approach to cross-platform development enables you to leverage native UI platforms. This does mean that you - the developer - do need to learn a bit about these platforms - and one of the key things to understand is the "view" lifecycle, including when used in navigation stacks.

默认情况下,MvvmCross不会在任何明显的时间长度内缓存视图模型.在屏幕转换(例如旋转)期间偶尔会出现短暂的缓存,但是不再有长期的缓存.相反,当创建一个新视图时,默认情况下mvx会创建一个新的视图模型以与该模型一起使用-该对模型终身"在一起-寿命终止由该视图确定.

By default MvvmCross does not cache view models for any significant length of time. There are occasional short-lived caches which occur during screen transitions (eg rotation) but there are no longer term caches. Instead, when a new view is created then mvx by default creates a new viewmodel to go with it - and that pair stay together "for life" - with the end of life being determined by the view.

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

I'd encourage you to take some time to read about the basic lifecycle and navigation paradigms on each platform.

  • 在iOS上,这意味着特别要学习有关UiNavigationController的知识,该UiNavigationController在内存中维护一堆UiViewControllers(每个在mvx中将与一个单独的视图模型结合)

  • on iOS this means especially learning about UiNavigationController which maintains a stack of UiViewControllers in memory (each of which will in mvx be married to an individual viewmodel)

WindowsPhone中的情况与此类似,其中RootFrame在RAM中保持一堆页面.这里有一个复杂的问题-墓碑墓葬-但是要等到基本生命周期确定之后再去做.

the situation is similar in WindowsPhone with the RootFrame maintaining in RAM a stack of pages. There is a complication here - tombstoning - but forget about that until after you get the basic lifecycle nailed.

在Android上,情况相似,但略有不同.对于基本应用程序,您可能会假设Android在应用程序的生命周期内将在RAM中维护一堆活动"页面.但是,Android实际上要比这复杂得多-操作系统在决定回收内存时可以从RAM中删除后退项.在这些情况下,有时需要担心一些墓碑"和脱水-但是,我再次建议您不要理会,直到掌握了基础知识为止.

on Android, the situation is similar, but slightly different. For basic apps you can probably assume that Android will maintain a stack of Activity pages in RAM during your app's lifetime. However, Android is actually far more complex than that - the OS can remove backstack items from RAM when it decides to reclaim memory. In these cases there's some 'tombstoning' and dehydration to sometimes worry about - but, again I'd recommend you ignore that until after you have the basics under the belt.

在winrt上,默认情况下实际上就是您在描述中所了解的-堆栈仅保存状态信息-视图本身未缓存在RAM中.

on winrt, by default the situation is actually what you understood in your description - the backstack only holds state information - the views themselves aren't cached in RAM.

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

The above stories hopefully give you some idea of view lifecycle in navigation stacks on each platform - and hence also give you the viewmodel lifecycle too.

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

Now, if you are in the situation that you want your viewmodels (or some other app level objects) to know about the view visibility state, then you'll need to intercept some view events on each platform and pass these events over to the view models.

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

For example, your FirstViewModel could expose OnMadeVisible() as a custom Api. In that case, you could ensure this were called from OnNavigatedTo on Windows, OnResume on Android and ViewDidAppear on iOS

或者,如果您正在查看ViewModel-ViewModel通信的通用机制,那么我建议您看一下

Alternatively if you are looking at general mechanisms for ViewModel-ViewModel communication then I would recommend you look at something like

  • the messenger use in the CollectABull tutorial in http://mvvmcross.wordpress.com
  • Greg's viewmodel result pattern on http://gregshackles.com

注意:

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

Obviously, navigation stacks are not the only navigation paradigm - if your app also uses flyouts, tabs, splitviews, hamburgers, etc then you'll need to understand those view lifecycles too.

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

If ever you are in doubt about View lifecycles, then adding trace to their constructors and key lifecycle events is a good first step,

最后一点,如果您确定默认的视图模型位置和视图模型生命周期不是您的应用程序所需要的-例如,如果您要使用单例视图模型,则可以轻松实现-查看覆盖您的视图模型定位器App.cs类.

As a final note, if you decide the default viewmodel location and viewmodel lifecycle is not what your app needs - eg if you want to use singleton viewmodels, then this can be easily achieved - look at overriding the view model locator in your App.cs class.

这篇关于MvvmCross ViewModel缓存并重新初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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