问题
I have a Xamarin Forms app, currently being built for Android. I have a MainActivity
that used to extend FormsApplicationActivity
, but because I want to use a custom theme I had to change it to extend FormsAppCompatActivity
(see my other question: Xamarin Forms custom theme not working).
Ever since changing from FormsApplicationActivity
to FormsAppCompatActivity
the app crashes whenever I switch out of the app and then back into the app. It throws an error in the App.xaml.cs
class in the OnResume
method, where I try to set the MainPage to a new navigation page:
protected override void OnResume()
{
bool isRegistered = _authenticationService.IsRegistered();
MainPage = isRegistered
? new NavigationPage(new LoginPage())
: new NavigationPage(new RegisterPage()); // this results in the crash
}
The error I'm getting is:
Java.Lang.IllegalStateException: Can not perform this action after onSaveInstanceState
This is the stacktrace:
03-09 13:43:52.098 I/MonoDroid( 1243): Java.Lang.IllegalStateException: Can not perform this action after onSaveInstanceState
03-09 13:43:52.098 I/MonoDroid( 1243): at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/2098/3efa14c4/source/mono/external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143
03-09 13:43:52.098 I/MonoDroid( 1243): at Android.Runtime.JNIEnv.CallIntMethod (IntPtr jobject, IntPtr jmethod) [0x00063] in /Users/builder/data/lanes/2098/3efa14c4/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:386
03-09 13:43:52.098 I/MonoDroid( 1243): at Android.Support.V4.App.FragmentTransactionInvoker.Commit () [0x00033] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.SwitchContentAsync (Xamarin.Forms.Page view, Boolean animated, Boolean removed, Boolean popToRoot) [0x000e1] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.OnPushAsync (Xamarin.Forms.Page view, Boolean animated) [0x00000] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.PushViewAsync (Xamarin.Forms.Page page, Boolean animated) [0x00000] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.<OnElementChanged>b__13_0 (Xamarin.Forms.Page p) [0x00000] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.EnumerableExtensions.ForEach[T] (IEnumerable`1 enumeration, System.Action`1 action) [0x00010] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.OnElementChanged (Xamarin.Forms.Platform.Android.ElementChangedEventArgs`1 e) [0x001af] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].SetElement (Xamarin.Forms.Platform.Android.TElement element) [0x000fc] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00027] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x0001f] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.RendererFactory.GetRenderer (Xamarin.Forms.VisualElement view) [0x00000] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.AppCompat.Platform.AddChild (Xamarin.Forms.Page page, Boolean layout) [0x00015] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.AppCompat.Platform.SetPage (Xamarin.Forms.Page newRoot) [0x00090] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.FormsAppCompatActivity.InternalSetPage (Xamarin.Forms.Page page) [0x0001a] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.FormsAppCompatActivity.AppOnPropertyChanged (System.Object sender, System.ComponentModel.PropertyChangedEventArgs args) [0x0001e] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.BindableObject.OnPropertyChanged (System.String propertyName) [0x00012] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Application.set_MainPage (Xamarin.Forms.Page value) [0x0008b] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Smartbit.App.OnResume () [0x00020] in C:\Users\leonc\Documents\Visual Studio 2015\Projects\Smartbit\Smartbit\Smartbit\App.xaml.cs:52
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Application.SendResume () [0x00006] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.FormsAppCompatActivity.OnStateChanged () [0x00039] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Xamarin.Forms.Platform.Android.FormsAppCompatActivity.OnRestart () [0x00019] in <filename unknown>:0
03-09 13:43:52.098 I/MonoDroid( 1243): at Android.App.Activity.n_OnRestart (IntPtr jnienv, IntPtr native__this) [0x00009] in /Users/builder/data/lanes/2098/3efa14c4/source/monodroid/src/Mono.Android/platforms/android-23/src/generated/Android.App.Activity.cs:4539
03-09 13:43:52.098 I/MonoDroid( 1243): at (wrapper dynamic-method) System.Object:cba7a870-1435-4f70-9059-e10915aba0c0 (intptr,intptr)
03-09 13:43:52.098 I/MonoDroid( 1243): --- End of managed exception stack trace ---
03-09 13:43:52.098 I/MonoDroid( 1243): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
03-09 13:43:52.098 I/MonoDroid( 1243): at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1448)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1466)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:634)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:613)
03-09 13:43:52.098 I/MonoDroid( 1243): at md5b60ffeb829f638581ab2bb9b1a7f4f3f.FormsAppCompatActivity.n_onRestart(Native Method)
03-09 13:43:52.098 I/MonoDroid( 1243): at md5b60ffeb829f638581ab2bb9b1a7f4f3f.FormsAppCompatActivity.onRestart(FormsAppCompatActivity.java:86)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.app.Instrumentation.callActivityOnRestart(Instrumentation.java:1181)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.app.Activity.performRestart(Activity.java:5291)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.app.Activity.performResume(Activity.java:5302)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2764)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2803)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1238)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.os.Handler.dispatchMessage(Handler.java:102)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.os.Looper.loop(Looper.java:136)
03-09 13:43:52.098 I/MonoDroid( 1243): at android.app.ActivityThread.main(ActivityThread.java:5001)
03-09 13:43:52.098 I/MonoDroid( 1243): at java.lang.reflect.Method.invokeNative(Native Method)
03-09 13:43:52.098 I/MonoDroid( 1243): at java.lang.reflect.Method.invoke(Method.java:515)
03-09 13:43:52.098 I/MonoDroid( 1243): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
03-09 13:43:52.098 I/MonoDroid( 1243): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
03-09 13:43:52.098 I/MonoDroid( 1243): at dalvik.system.NativeStart.main(Native Method)
回答1:
I had the similiar issue. There are few points about it:
1) Move your MainPage setting code to App constructor. As MainPage should be set in OnCreate method.
public App () {
MainPage = isRegistered
? new NavigationPage(new LoginPage())
: new NavigationPage(new RegisterPage());
}
2) You need to set you root page before OnCreate finishes. As you do not know the page you need, you may just set blanc page.
public App () {
MainPage = new ContentPage();
}
3) If this does not help. You can simply add try/catch block abound MainPage setter. This is dirty solution, but it works. In AppCompatActivity xamarin uses Fragments not Views. The crash happens, when android tries to restore fragment state. On plain android we used to use CommitAllowingStateLoss().
try{
MainPage = isRegistered
? new NavigationPage(new LoginPage())
: new NavigationPage(new RegisterPage());
}catch(Exception){}
回答2:
I solved it by adding a thread sleep in my OnResume method before setting the MainPage. My OnResume now looks like this:
protected override void OnResume()
{
base.OnResume();
Task.Delay(10).Wait();
bool isRegistered = _authenticationService.IsRegistered();
MainPage = isRegistered
? new NavigationPage(new LoginPage())
: new NavigationPage(new RegisterPage());
}
See this bug report for this workaround.
来源:https://stackoverflow.com/questions/35892598/app-resuming-results-in-crash-with-formsappcompatactivity