【问题标题】:MonoCross: KeyNotFoundException in MXDialogActivityView.OnCreate() when re-starting applicationMonoCross:重新启动应用程序时 MXDialogActivityView.OnCreate() 中的 KeyNotFoundException
【发布时间】:2013-05-18 19:49:25
【问题描述】:

我一直在使用 Xamarin 的 Mono for Android 和 MonoCross 框架来开发一个应用程序,该应用程序目前在 Android(2.3、4.0 和其他)下运行。 在我的应用程序中,我有一个主要活动,用户可以从那里开始新活动,然后再次开始其他活动等等。 (例如 Main -> A -> B -> C)

有时,我会遇到以下问题: 当应用程序暂停(或停止)一段时间(即不在前台),和/或启动其他消耗内存的应用程序,然后我返回我的应用程序时,它没有正确重新启动。 这意味着,我可以看到部分活动 C(窗口标题)几秒钟,然后 C 消失,B 出现,以此类推,A 和 Main。 Main 消失后,我又回到了主屏幕。当我再次启动我的应用程序时,它会与 Main Activity 一起启动。

在 logcat 中,我看到了这些条目(希望我没有删减太多):

05-15 14:36:39.732 I/ActivityManager(  598): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=de.branchare.adwais2013/branchware.adwais.droid.MainActivity u=0} from pid 1349
...
05-15 14:36:39.792 I/ActivityManager(  598): Start proc de.branchare.adwais2013 for activity de.branchare.adwais2013/branchware.adwais.droid.views.ActivityC: pid=29032 uid=10025 gids={3003, 1015, 1028}
...
05-15 14:36:39.952 I/ActivityThread(29032): Pub de.branchare.adwais2013.mono.MonoRuntimeProvider.__mono_init__: mono.MonoRuntimeProvider
...
05-15 14:36:42.966 I/MonoDroid(29032): at MonoCross.Droid.MXDialogActivityView`1<Branchware.Adwais.ModelContainer`1<Branchware.Adwais.Model.Visit>>.OnCreate (Android.OS.Bundle) <0x00053>
05-15 14:36:42.966 I/MonoDroid(29032): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) <0x00057>
05-15 14:36:42.966 I/MonoDroid(29032): at (wrapper dynamic-method) object.15bfff07-188b-4aff-a34f-ab878a2a545f (intptr,intptr,intptr) <0x00043>
05-15 14:36:43.036 E/mono    (29032):
05-15 14:36:43.036 E/mono    (29032): Unhandled Exception:
05-15 14:36:43.036 E/mono    (29032): System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
05-15 14:36:43.036 E/mono    (29032):   at System.Collections.Generic.Dictionary`2[System.Type,System.Object].get_Item (System.Type key) [0x00000] in <filename unknown>:0
05-15 14:36:43.036 E/mono    (29032):   at MonoCross.Droid.MXDialogActivityView`1[Branchware.Adwais.ModelContainer`1[Branchware.Adwais.Model.Visit]].OnCreate (Android.OS.Bundle bundle) [0x00000] in <filename unknown>:0
05-15 14:36:43.036 E/mono    (29032):   at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) [0x00000] in <filename unknown>:0
05-15 14:36:43.036 E/mono    (29032):   at (wrapper dynamic-method) object:15bfff07-188b-4aff-a34f-ab878a2a545f (intptr,intptr,intptr)
05-15 14:36:43.036 I/mono    (29032): [ERROR] FATAL UNHANDLED EXCEPTION: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
05-15 14:36:43.036 I/mono    (29032):   at System.Collections.Generic.Dictionary`2[System.Type,System.Object].get_Item (System.Type key) [0x00000] in <filename unknown>:0
05-15 14:36:43.036 I/mono    (29032):   at MonoCross.Droid.MXDialogActivityView`1[Branchware.Adwais.ModelContainer`1[Branchware.Adwais.Model.Visit]].OnCreate (Android.OS.Bundle bundle) [0x00000] in <filename unknown>:0
05-15 14:36:43.036 I/mono    (29032):   at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) [0x00000] in <filename unknown>:0
05-15 14:36:43.036 I/mono    (29032):   at (wrapper dynamic-method) object:15bfff07-188b-4aff-a34f-ab878a2a545f (intptr,intptr,intptr)
05-15 14:36:43.136 I/ActivityManager(  598): Recipient 29032
05-15 14:36:43.136 I/ActivityManager(  598): Process de.branchare.adwais2013 (pid 29032) has died.
05-15 14:36:43.136 D/InputManager(  598): setFocusedApplication Exception: java.lang.NullPointerException
...
05-15 14:36:43.136 W/ActivityManager(  598): Force removing ActivityRecord{41cc9df0 de.branchare.adwais2013/branchware.adwais.droid.views.ActivityC}: app died, no saved state
...
05-15 14:36:43.166 I/ActivityManager(  598): Start proc de.branchare.adwais2013 for activity de.branchare.adwais2013/branchware.adwais.droid.views.ActivityB: pid=29052 uid=10025 gids={3003, 1015, 1028}

在我看来好像
- Android 在我的活动暂停时销毁()了我的活动(我知道这是正确的行为)
- 当用户返回我的应用程序时,Android 会尝试 Create() 活动的新实例(这也是正确的)
- 在框架的 MXDialogActivityView.OnCreate() 中,MonoCross 在调用 Render() 之前尝试从 MXDroidContainer 中获取模型:

// fetch the model before rendering!!!  
Model = (T)MXDroidContainer.ViewModels[typeof(T)];  
// render the model within the view  
Render();  

- 这是引发 KeyNotFoundException 的地方(永远不会调用 Render() 方法),因为 MXDroidContainer 不再包含 ViewModel。 (可能同时此实例也被重新创建,因此不包含任何数据。)

我知道 Android 可以(甚至必须)销毁暂停/停止的应用程序。 但是看着我的应用程序返回整个活动堆栈然后完全消失,并且不得不重新启动它,这非常烦人。

我想要实现的是:
a) 我的应用应该在它停止的地方重新启动(在活动 C 中)。
如果这是不可能的,那么
b) 我的应用应该在 MainLauncher(在 Main 活动中)重新启动,完全重新初始化。

我已经阅读(并玩过)很多关于活动生命周期、启动模式、AlwaysRetainTaskState 的内容...... 但是我还没有找到解决问题的方法。

任何帮助或指点将不胜感激。

TIA, 曼弗雷德。

【问题讨论】:

    标签: android-activity xamarin.android monocross


    【解决方案1】:

    我认为您对 Activity 生命周期及其与 MonoCross 框架交互的分析是正确的。

    我不确定 MonoCross 目前是否对这种“墓碑”有任何处理 - 所以如果你想处理这个,那么你需要自己做。

    为此,您需要:

    • 使用protected override void OnSaveInstanceState(Bundle outState) 方法将视图的任何当前模型数据保存/序列化到包中
    • 覆盖默认的MX*ActivityView.OnCreate 行为,以便使用包含已保存实例状态的bundle 参数。

    我最近在 MvvmCross 中做过同样类型的事情。然而,模型的生命周期在 MvvmCross 中是非常不同的——我相信 MonoCross 总是在内存中保留每个模型的一个实例,而 MvvmCross 只是将每个 View 链接到它的 ViewModel——所以 ViewModel 生命周期与 View 生命周期精确相关。因此,我担心 Mvx 代码可能无法轻松移植回 MX...

    【讨论】:

    • 嗨 Stuart,非常感谢您的快速回答。我在放假,所以我刚刚读了它。我会试试捆绑的东西。我有一些 ListViews 包含具有数百个条目的模型,这似乎不容易(和快速)保存在 OnSaveInstanceState() 中。但我想我可以保存参数字典,然后重新导航到视图。再次感谢这一点。顺便说一句:有没有人在使用 MonoCross 框架?我的印象是那里没有太多的活动。再见,曼弗雷德。
    • 顺便说一句,我认为你最好的办法是在他们的 Google Group 上提问。我在 Evolve 与 ITR 的两个人进行了交谈,他们谈到了很多客户和用户 - 并提到他们的新版本即将推出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多