MvvmCross Android - 重新加载 Fragments 时 ViewModel 报 Null Reference 错误

3

源代码 - https://github.com/benhysell/V.FlyoutTest/

问题 - 在混合使用片段和基础视图并在设备设置中使用“开发者选项/不保留活动”时,如果调用OnDestory()并将活动重新带回视图,则ViewModels为空。这会导致空引用异常和应用程序崩溃。

描述 我在Android上使用MvvmCross实现了一个侧滑/汉堡菜单。在应用程序启动时,以下步骤将执行:

  • HomeViewModel 设置为加载
  • HomeViewModel 加载 HomeView 并设置侧滑/汉堡菜单
  • 由于 HomeView 从未真正显示过,只是管理它调用并显示 EnterTimeViewModel,也就是默认视图,我们真正关心的视图。
  • 在加载 HomeView 结束时,使用 messenger 插件生成一条消息来“登录”到系统中
  • EnterTimeViewModel 中接收到消息,通常情况下,我们需要进行某些检查以查看是否已登录,但在这种情况下,我们只需调用 ShowViewModel 来模拟登录请求并提示用户。

  • LoginViewModel 不是片段,而只是普通的基础视图。它向用户展示

  • 同时,由于我们设置了“开发者选项/不保留活动”,HomeView 正在被从系统中移除
  • 用户通过单击登录来登录到系统中,在演示中,这是一个无操作,并且它只关闭 LoginView
  • 然后恢复 HomeView,但在此过程中,EnterTimeViewModel 为空……当 EnterTime 视图试图访问 EnterTimeViewModel 时会遇到空引用。

关于 MvvmCross 过渡的事件序列如下所示,而加载和卸载 HomeView:

  • OnCreate
  • StartActivityForResult
  • OnStart
  • OnResume
  • OnPause
  • OnSaveInstanceState
  • OnStop
  • OnDestroy

显示登录屏幕,登录后

  • OnCreate
  • OnStart
  • Crash,空引用异常

感觉跳过了一些步骤,导致崩溃。有什么想法吗?去哪里看?

作为参考,我基于的项目,https://github.com/jamesmontemagno/Xam.NavDrawer 也存在相同的问题。

更新 实现了一个修复方案,解决了http://benjaminhysell.com/archive/2014/06/mvvmcross-flyoutnavigation-hamburger-menu-sliding-menu-for-android-null-reference-exception-on-fragment-shown-fix/中提到的空引用异常问题。简而言之,我们承担起保存ViewModels的责任,最坏情况下也会在片段被卸载内存时重新创建它们。
1个回答

6

从你的代码来看,当你第一次创建碎片时,似乎是手动设置 ViewModel:

            frag.ViewModel = viewModelLocal;

来自https://github.com/benhysell/V.FlyoutTest/blob/master/V.FlyoutTest.Droid/Views/HomeView.cs#L153

当您的托管Activity由于“不保留活动”而被关闭,然后再次显示时,Android会在instanceState bundle中保存片段状态,并尝试重新创建这些片段-这可能是您看到NullReferenceException的时候。

要解决此问题,您需要:

  • 找到一种方法,在bundle存在时在OnCreateView期间重新创建您的ViewModel。您可以使用序列化/反序列化技术或将ViewModel = viewModelLocal代码移动到OnCreateView方法内部,而不是在拥有的Activity内部
  • 阻止默认的Android片段重建(例如通过停止父bundle使用其OnCreatebundle并使用自己的重新膨胀逻辑)

注意:对于Activity,此行为不会发生,因为MvvmCross可以重用那里的Intent以重新创建Activity的ViewModel。但对于Fragment,应用程序已经负责创建这些(在其自定义Presenter中),因此目前应用程序也必须负责重新创建ViewModel


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接