简体   繁体   English

重新启动应用程序时,MXDialogActivityView.OnCreate()中的MonoCross:KeyNotFoundException

[英]MonoCross: KeyNotFoundException in MXDialogActivityView.OnCreate() when re-starting application

I've been using Xamarin's Mono for Android and the MonoCross framework to develop an application, which is currently running under Android (2.3, 4.0 and others). 我一直在使用Xamarin的Android版Mono和MonoCross框架来开发应用程序,该应用程序目前在Android(2.3、4.0和其他版本)下运行。 In my app, I have a main activity, from where the user can start new activities, which again start other activities and so on. 在我的应用程序中,我有一个主要活动,用户可以从中开始新活动,然后再开始其他活动,依此类推。 (eg Main -> A -> B -> C) (例如Main-> A-> B-> C)

From time to time, I get following problem: When the application is paused (or stopped) for some time (ie not in the foreground), and/or other memory consuming apps are started, and then I return to my app, it isn't restarted correctly. 有时,我会遇到以下问题:当应用程序暂停(或停止)一段时间(即不在前台)和/或启动了其他消耗内存的应用程序,然后又返回到我的应用程序时,无法正确重启。 That means, I can see parts of activity C (the window title) for some seconds, then C disappears, B comes and so on with A and Main. 就是说,我可以看到活动C(窗口标题)的一部分持续几秒钟,然后C消失,B出现,以此类推,A和Main依此类推。 After Main disappears, I am back on the home screen. Main消失后,我回到主屏幕。 When I again start my app, it launches with the Main activity. 当我再次启动我的应用程序时,它将以Main活动启动。

In logcat, I see these entries (I hope I didn't cut too much): 在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}

It seems to me as if 在我看来
- Android has Destroy()ed my activities while they were paused (which I know is correct behavoir) -Android在活动暂停时销毁了我的活动(我知道这是正确的行为)
- Android then tries to Create() new instances of the activities when the user returns to my app (which is correct, too) -然后,当用户返回我的应用程序时,Android会尝试创建()新的活动实例(也是正确的)
- In the framework's MXDialogActivityView.OnCreate(), MonoCross tries to fetch the model from the MXDroidContainer before calling Render(): -在框架的MXDialogActivityView.OnCreate()中,MonoCross尝试在调用Render()之前从MXDroidContainer中获取模型:

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

- This is where the KeyNotFoundException is thrown (the method Render() is never called), because the MXDroidContainer does not contain the ViewModels any longer. -这是抛出KeyNotFoundException的地方(从不调用Render()方法),因为MXDroidContainer不再包含ViewModel。 (Probably this instance was also re-created in the meantime, and therefore does not contain any data.) (此实例可能也在此期间重新创建,因此不包含任何数据。)

I know that Android can (or even must) destroy paused/stopped apps. 我知道Android可以(甚至必须)销毁已暂停/已停止的应用程序。 But it's very annoying to watch my app going back the whole activity stack and then disappearing completely, and having to re-re-start it. 但是看到我的应用返回整个活动堆栈然后完全消失,然后不得不重新启动它,这真是令人讨厌。

What I would like to achieve is: 我想要实现的是:
a) My app should restart where it stopped (in activity C). a)我的应用程序应在停止的位置(在活动C中)重新启动。
If that's not possible, then 如果不可能的话
b) My app should restart at the MainLauncher (in activity Main), completely re-initialized. b)我的应用程序应该在MainLauncher(活动Main)中重新启动,并完全重新初始化。

I've already read (and played around with) a lot about activity lifecycle, launch modes, AlwaysRetainTaskState, ... But I did not yet find a solution to my problem. 我已经阅读(并玩过)很多有关活动生命周期,启动模式,AlwaysRetainTaskState等的信息,但是我还没有找到解决问题的方法。

Any help or pointers would be greatly appreciated. 任何帮助或指针将不胜感激。

TIA, Manfred. TIA,曼弗雷德。

I think your analysis of the Activity lifecycle and its interaction with the MonoCross framework is correct. 我认为您对Activity生命周期及其与MonoCross框架的交互的分析是正确的。

I'm not sure if MonoCross has any handling currently for this kind of 'tombstoning' - so if you want to handle this, then you'll need to do do so yourself. 我不确定MonoCross目前是否对这种“墓碑化”有任何处理-因此,如果您要处理此问题,则需要自己进行。

To do this, you'll need to: 为此,您需要:

  • use the protected override void OnSaveInstanceState(Bundle outState) method to save/serialise any current Model data for your View into the Bundle 使用protected override void OnSaveInstanceState(Bundle outState)方法将视图的任何当前Model数据保存/序列化到Bundle中
  • override the default MX*ActivityView.OnCreate behaviour in order to use the bundle parameter which will contain the saved instance state. 覆盖默认的MX*ActivityView.OnCreate行为,以便使用将包含已保存实例状态的bundle参数。

I've done this same type of thing recently within MvvmCross. 我最近在MvvmCross中完成了相同类型的操作。 However, the lifecycle of models is very different in MvvmCross - I believe MonoCross always keeps exactly one instance of each model in memory, whereas MvvmCross just links each View to its ViewModel - so the ViewModel lifecyle is tied precisely to the View lifecyle. 但是,模型的生命周期在MvvmCross中是非常不同的-我相信MonoCross总是在内存中始终保留每个模型的一个实例,而MvvmCross只是将每个View链接到其ViewModel-因此ViewModel生命周期与View生命周期紧密地联系在一起。 Because of this I'm afraid that Mvx code may not port easily back to MX... 因此,我担心Mvx代码可能无法轻松移植回MX ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM