“Can not perform this action after onSaveInstanceState” - why am I getting this exception from my activity's onResume method?

后端 未结 7 640
北海茫月
北海茫月 2020-12-08 02:25

My activity invokes the camera with the ACTION_IMAGE_CAPTURE intent. If the camera activity returns succesfully, I set a flag in the onActivityResult callback, and based on

相关标签:
7条回答
  • 2020-12-08 03:16

    Update I think I have found an explanation and a solution here: http://code.google.com/p/android/issues/detail?id=23096#c4 I implemented the Empty Fragment Workaround posted there and got no more IllegalStateException so far.

    I add the invisible state fragment in my activity like this;

    @Override
    protected void onCreate(final Bundle args) {
        ...
        if (args == null) {
            final FragmentManager fm = this.getSupportFragmentManager();
            final FragmentTransaction ft = fm.beginTransaction();
            final Fragment emptyFragmentWithCallback = new EmptyFragmentWithCallbackOnResume();
            ft.add(emptyFragmentWithCallback, EmptyFragmentWithCallbackOnResume.TAG);
            ft.commit();
        }
    

    The following code is taken from above link:

    public class EmptyFragmentWithCallbackOnResume extends Fragment {
    OnFragmentAttachedListener mListener = null;
    
    @Override
    public void onAttach(SupportActivity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentAttachedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnFragmentAttachedListener");
        }
    }
    
    @Override
    public void onResume() {
        super.onResume();
        if (mListener != null) {
            mListener.OnFragmentAttached();
        }
    }
    
    public interface OnFragmentAttachedListener {
        public void OnFragmentAttached();
    }
    }
    

    and invoke fragment transactions that would intuitively go into onResume or onResumeFragments into my custom onFragmentAttached method that is invoked by the invisible state fragment. I do not use onResumeFragments at all and do not issue any fragment transactions in onResume.

    So, to sum it up. If you are using the support lib and fragments, pretty much forget about onResume, forget about onResumeFragments and implement your own "onResume" based on the above workaround. This is somewhat ridiculous.


    I cannot confirm. I have the exact same problem. even though I am issuing fragment transaction in onResumeFragments. This used to work as I posted here: IllegalStateException - Fragment support library .

    It seems the error only occurs on 4.0.3 and 4.0.4. However it does neither occur always nor in my Emulator.

    I am using support lib rev. 10 and API 16. I call DialogFragment.show in onResumeFragments and continously get this ridiculous exception from some random users. I cannot reproduce it locally.

    0 讨论(0)
  • 2020-12-08 03:17

    I was always getting this when I tried to show fragment in onActivityForResult() method, so the problem was next:

    1. My Activity is paused and stopped, which means, that onSaveInstanceState() was called already (for both pre-Honeycomb and post-Honeycomb devices).
    2. In case of any result I made transaction to show/hide fragment, which causes this IllegalStateException.

    What I made is next:

    1. Added value for determining if action I want was done (e.g. taking photo from camere - isPhotoTaken) - it can be boolean or integer value depending how much different transactions you need.
    2. In overriden onResumeFragments() method I checked for my value and after made fragment transactions I needed. In this case commit() was not done after onSaveInstanceState, as state was returned in onResumeFragments() method.
    0 讨论(0)
  • 2020-12-08 03:18

    you can use the method commitAllowingStateLoss()

    but be aware you can lose the state of your activity as you can see in google's android reference which explain the different between the two in the following way

    Like commit() but allows the commit to be executed after an activity's state is saved. This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.

    from my experience it may cause the addToBackStack method not to work sometimes so you will need to add it manually on the fragment and of course the state won't be saved (textbox text ext.)

    0 讨论(0)
  • 2020-12-08 03:18

    Add this to your Activity:

     @Override
        protected void onSaveInstanceState(Bundle outState) {
            //No call for super(). Bug on API Level > 11.
        }
    
    0 讨论(0)
  • 2020-12-08 03:20

    I think I know the answer - I'm using the FragmentActivity from v4 compatibility library, and so I need to perform my fragment transactions in onResumeFragments instead of in onResume. Can someone confirm?

    0 讨论(0)
  • 2020-12-08 03:21

    this worked for me... found this out on my own... hope it helps you!

    1) do NOT have a global "static" FragmentManager / FragmentTransaction.

    2) onCreate, ALWAYS initialize the FragmentManager again!

    sample below :-

    public abstract class FragmentController extends AnotherActivity{
    protected FragmentManager fragmentManager;
    protected FragmentTransaction fragmentTransaction;
    protected Bundle mSavedInstanceState;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSavedInstanceState = savedInstanceState;
        setDefaultFragments();
    }
    
    protected void setDefaultFragments() {
        fragmentManager = getSupportFragmentManager();
        //check if on orientation change.. do not re-add fragments!
        if(mSavedInstanceState == null) {
            //instantiate the fragment manager
    
            fragmentTransaction = fragmentManager.beginTransaction();
    
            //the navigation fragments
            NavigationFragment navFrag = new NavigationFragment();
            ToolbarFragment toolFrag = new ToolbarFragment();
    
            fragmentTransaction.add(R.id.NavLayout, navFrag, "NavFrag");
            fragmentTransaction.add(R.id.ToolbarLayout, toolFrag, "ToolFrag");
            fragmentTransaction.commitAllowingStateLoss();
    
            //add own fragment to the nav (abstract method)
            setOwnFragment();
        }
    }
    
    0 讨论(0)
提交回复
热议问题