当设备的方向改变时,简单代码抛出IllegalStateException

时间:2016-08-14 09:11:06

标签: java android xamarin

等待app开始。旋转设备。点击查看。异常。

Project code here

为什么我会收到此异常?

MainActivity.cs

[Activity (Label = "OrientationChangeFragmentCommit", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity : Activity
{
    const string currentFragmentTag = "currentFragment";

    protected override void OnCreate (Bundle savedInstanceState)
    {
        base.OnCreate (savedInstanceState);

        SetContentView (Resource.Layout.Main);

        if (GetCurrentFragment() == null)
        {
            BlueFragment frag = new BlueFragment();
            frag.AuthTcs.Task.ContinueWith(task =>
            {
                try
                {
                    RunOnUiThread(() => FragmentManager.PopBackStackImmediate());
                }
                catch (Exception exc)
                {
                    //exception here
                }
            });
            AddFrag(this, frag, Resource.Id.fragmentContainer);
        }
    }

    void AddFrag(Activity act, Fragment frag, int containerId)
    {
        FragmentTransaction fragmentTx = act.FragmentManager.BeginTransaction();
        fragmentTx.Add(containerId, frag, currentFragmentTag);
        fragmentTx.AddToBackStack(null);
        fragmentTx.Commit();
    }

    Fragment GetCurrentFragment()
    {
        var f = FragmentManager.FindFragmentByTag (currentFragmentTag);
        return f;
    }
}

BlueFragment.cs

public class BlueFragment : Fragment
{
    public TaskCompletionSource<bool> AuthTcs = new TaskCompletionSource<bool>();
    public override void OnCreate (Bundle savedInstanceState)
    {
        base.OnCreate (savedInstanceState);
        RetainInstance = true;
    }

    public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        base.OnCreateView (inflater, container, savedInstanceState);

        var view = new LinearLayout (inflater.Context);
        view.Orientation = Orientation.Vertical;
        view.SetBackgroundColor (Color.Blue);
        ViewGroup.LayoutParams par = new ViewGroup.LayoutParams (ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);
        view.LayoutParameters = par;
        view.AddView(new View(inflater.Context));

        view.Click += (s, e) =>
        {
            AuthTcs.TrySetResult(true);
        };

        return view;
    }
}

Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/fragmentContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

异常说:Java.Lang.IllegalStateException:onSaveInstanceState之后无法执行此操作

2 个答案:

答案 0 :(得分:0)

替换代码中的行

fragmentTx.Commit();

使用以下代码

fragmentTx.commitAllowingStateLoss();

有关详细信息,请参阅以下链接:

http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

答案 1 :(得分:0)

正确的代码是:

frag.AuthTcs.Task.ContinueWith(task =>
    {
        RunOnUiThread (() => frag.Activity.FragmentManager.PopBackStackImmediate ());
    });

因为lambda函数存储了对旧活动的引用,因此存储了旧的FragmentManager。