Android活动状态丢失

6 android android-activity

有人可以为我回答这个问题:

出于测试目的,我创建了一个带有for循环的活动,其中我创建了10个AlertDialogs或10个DialogFragments.活动开始后,我立即按主页按钮在后台发送应用程序.如果我正在运行showDialog()方法来创建DialogFragments,则应用程序将崩溃:

IllegalStateException: Can not perform this action after onSaveInstanceState
Run Code Online (Sandbox Code Playgroud)

这是预期的行为.

但是,如果我运行showAlert()方法来创建AlertDialogs,就像我将应用程序发送到后台之前一样,应用程序不会崩溃.当我回到活动时,我可以看到所有10个AlertDialogs.

问题是为什么活动状态丢失发生在DialogFragment而不是AlertDialog?

保存活动状态后,我仍在更改UI.我测试过的平台是Android 4.4.2

public class Main extends FragmentActivity
{
    private FragmentActivity activity = this;
    private MyAsynk myAsynk;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_main);

        myAsynk = new MyAsynk();
        myAsynk.execute();
    }

    private class MyAsynk extends AsyncTask<Void, Void, Void>
    {
        private boolean run = false;

        public MyAsynk()
        {
            run = true;
        }

        @Override
        protected Void doInBackground(Void... params)
        {
            for(int i = 0; i < 10 && run; i++)
            {
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }

//              showAlert("loop " + i);
                showDialog("loop " + i);
            }

            return null;
        }

        public void stop()
        {
            run = false;
        }
    }


    @Override
    public void onBackPressed()
    {
        super.onBackPressed();

        if(null != myAsynk)
        {
            myAsynk.stop();
            myAsynk = null;
        }
    }


    private void showAlert(final String txt)
    {
        try
        {
            Main.this.runOnUiThread(new Runnable()
            {
                @Override
                public void run()
                {
                    new AlertDialog.Builder(activity).setMessage(txt)
                    .setPositiveButton("Ok", new DialogInterface.OnClickListener()
                    {
                        @Override
                        public void onClick(DialogInterface dialog, int which)
                        {
                            try
                            {
                                if(null != dialog)
                                {
                                    dialog.dismiss();
                                }
                            }
                            catch(Exception e)
                            {
                                e.printStackTrace();
                            }
                        }
                    })
                    .show();
                }
            });
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    } 


    private void showDialog(final String txt)
    {
        try
        {
            Main.this.runOnUiThread(new Runnable()
            {
                @Override
                public void run()
                {
                    MyDialogFragment newFragment = MyDialogFragment.newInstance(txt);
                    FragmentTransaction ft = Main.this.getSupportFragmentManager().beginTransaction();

                    newFragment.show(ft, "newFragment");
                }
            });
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

MyDialogFragment.java:

public class MyDialogFragment extends DialogFragment
{
    private MyDialogFragment instance;

    public static MyDialogFragment newInstance(String text)
    {
        MyDialogFragment f = new MyDialogFragment();

        Bundle args = new Bundle();
        args.putString("text", text);
        f.setArguments(args);

        return f;
    }

    public MyDialogFragment()
    {
        instance = this;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View v = inflater.inflate(R.layout.my_dialog_fragment, container, false);
        TextView tv = (TextView) v.findViewById(R.id.tv);
        Button bu = (Button) v.findViewById(R.id.bu);

        bu.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                try
                {
                    if(null != instance && instance.isVisible())
                    {
                        instance.dismiss(); 
                    }
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        });

        tv.setText(getArguments().getString("text"));

        return v;
    }
}
Run Code Online (Sandbox Code Playgroud)

mat*_*ash 1

答案很简单,尽管有点平淡。

常见的java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState异常实际上是由FragmentManager类抛出的。Alex Lockwood在这篇文章中很好地解释了原因。

DialogFragments是片段(因此由 管理FragmentManager)。因此,以这种方式显示对话框可能会引发异常。然而,它的实现AlertDialog完全不同:它根本不使用 Fragments(事实上,它实际上早于 Fragments)。因此,没有例外。