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

风流意气都作罢 提交于 2019-12-24 15:27:35

问题


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). In my app, I have a main activity, from where the user can start new activities, which again start other activities and so on. (e.g. Main -> A -> B -> C)

From time to time, I get following problem: When the application is paused (or stopped) for some time (i.e. 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. After Main disappears, I am back on the home screen. When I again start my app, it launches with the Main activity.

In logcat, I see these entries (I hope I didn't cut too much):

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 then tries to Create() new instances of the activities when the user returns to my app (which is correct, too)
- In the framework's MXDialogActivityView.OnCreate(), MonoCross tries to fetch the model from the MXDroidContainer before calling Render():

// 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. (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. 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).
If that's not possible, then
b) My app should restart at the MainLauncher (in activity Main), completely re-initialized.

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.

Any help or pointers would be greatly appreciated.

TIA, Manfred.


回答1:


I think your analysis of the Activity lifecycle and its interaction with the MonoCross framework is correct.

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.

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
  • override the default MX*ActivityView.OnCreate behaviour in order to use the bundle parameter which will contain the saved instance state.

I've done this same type of thing recently within 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. Because of this I'm afraid that Mvx code may not port easily back to MX...



来源:https://stackoverflow.com/questions/16605354/monocross-keynotfoundexception-in-mxdialogactivityview-oncreate-when-re-start

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!