58

I have a fragment;

MyFragment myFrag = new MyFragment();

I put bundle data to this fragment:

Bundle bundle = new Bundle(); 
bundle.putString("TEST", "test");
myFrag.setArguments(bundle);

Then, I replace old fragment with this one and put on backstack:

//replace old fragment
fragmentTransaction.replace(R.id.fragment_placeholder, myFrag, "MyTag");
//put on backstack
fragmentTransaction.addToBackStack(null);
//commit & get transaction ID
int transId = fragmentTransaction.commit();

Later, I pop backstack with the above transaction ID(transId):

//pop the transaction from backstack
fragmentManager.popBackStack(transId,FragmentManager.POP_BACK_STACK_INCLUSIVE); 

Later, I set bundle data as argument again to my fragment(myFrag):

//Got Java.lang.IllegalStateException: fragment already active
myFrag.setArguments(bundle);

As you see, my above code got exception Java.lang.IllegalStateException: fragment already active . I don't understand why myFrag is still active though I have popped the transaction of it from backstack., anyhow, since I got the exception I thought I have no choice but de-active the fragment, So, I did:

Fragment activeFragment = fragMgr.findFragmentByTag("MyTag");
fragmentTransaction.remove(activeFragment);

I am not sure if my above code really can de-active the fragment, since I didn't find how to de-active an fragment. :(

After that, when I try to set bundle data to my fragment myFrag again, I still got the same error:

Java.lang.IllegalStateException: fragment already active

Seems even I removed the fragment, it is still active...Why? How to de-active a fragment?

Leem.fin
  • 40,781
  • 83
  • 202
  • 354

8 Answers8

152

Reading the setArguments(Bundle args) source will help you understand:

/**
* Supply the construction arguments for this fragment.  This can only
* be called before the fragment has been attached to its activity; that
* is, you should call it immediately after constructing the fragment.  The
* arguments supplied here will be retained across fragment destroy and
* creation.
*/
public void setArguments(Bundle args) {

    if (mIndex >= 0) {
        throw new IllegalStateException("Fragment already active");
    }
    mArguments = args;
}

You cannot use setArguments(Bundle args) again in your code on the same Fragment. What you want to do I guess is either create a new Fragment and set the arguments again. Or you can use getArguments() and then use the put method of the bundle to change its values.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Assaf Gamliel
  • 11,935
  • 5
  • 41
  • 56
  • 54
    +1 for "you can use getArguments() and then use the put methods of bundle to change it's values." – Saran Aug 28 '13 at 13:54
  • Here is very good example with detail explanation as well. http://emuneee.com/blog/2013/01/07/saving-fragment-states/ – Hesam Nov 26 '14 at 02:49
  • 25
    `getArguments().putAll(bundle);` will overwrite the whole bundle – DeltaCap019 Dec 09 '14 at 11:53
  • 2
    `getArguments().putAll(bundle);` does not Override the whole bundle. I still have my previous key and value after calling this one. In my case, I've used `getArguments().clear();` and it cleaned up the Arguments. – osayilgan Jun 02 '15 at 21:21
  • You can not use getArguments().putAll() if you not sets setArguments() previusly because getArguments() returns null. – David Jul 31 '17 at 05:48
  • Do I have to put setArguments(args); again? – Shubham Agarwal Bhewanewala Sep 09 '17 at 17:47
1

Try removing the previous fragment before adding the new one: https://stackoverflow.com/a/6266144/969325

Community
  • 1
  • 1
Warpzit
  • 27,966
  • 19
  • 103
  • 155
  • I tried firstly "fragmentTransaction.remove(myFrag)" then "replace(...)" , it does not help. I got the same exception – Leem.fin Apr 28 '12 at 15:09
  • nono The PREVIOUS. so whatever is on the stack is removed with remove and then you replace with myfrag. – Warpzit Apr 28 '12 at 15:45
  • `fragmentTransaction.remove(myFrag)` removes the fragment from its `addedFragment` stack but keep its instance in its `activeFragment` stack. – DeltaCap019 Dec 09 '14 at 11:34
1

remove() change fragment status to de-actiive. In your case, you just didn't call commit() after remove(..).

fragmentTransaction.remove(activeFragment);

You would do commit() after remove(), too.

fragmentTransaction.remove(activeFragment).commit();
Dog발자
  • 86
  • 1
  • 6
0

Had the same issue. I was adding the fragment to backstack. And the error was because I didn't call popbackstack(). Using popbackstack helped me

Zhangali Bidaibekov
  • 591
  • 1
  • 7
  • 13
0

I'm running into the same issue on Xamarin.android. Here's what the documentation says.

This can only be called before the fragment has been attached to its activity

Jonathan
  • 648
  • 4
  • 13
  • 34
0

Just call public method from fragment

if(userFragment==null){
                    userFragment = new UserFragment();
                    Bundle bundle = new Bundle();
                    bundle.putString(Constants.EXTRA_CUSTOMER, result);
                    userFragment.setArguments(bundle);
                }else{
                    try {
                        Customer customer = new Customer();
                        customer.parseCustomer(new JSONObject(result));
                        userFragment.updateVeiw(customer);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
0

First I start with describing why this happens and then I'll come up with the solution I found working... .

This issue happens when Android is removing the fragment from the stack but is not yet finished with removing. In order to check this, you can use the isRemoving() method of the fragment. If false, i.e. the fragment is not active, you can go on with setting the arguments using setArguments(bundle). Otherwise, you can't set arguments to an already active fragment and can only override it by addressing the same arguments using getArguments().putAll(bundle).

To summarize,

    if (myFrag.isRemoving()) {
        myFrag.getArguments().putAll(bundle);
    } else {
        myFrag.setArguments(bundle);
    }

If you want to avoid this, i.e. removing the fragment at once so there is no active fragment, you might want to use onBackPressed() in onBackStackChangedListener(), which will set the isRemoving() to false.

Ali Nem
  • 5,252
  • 1
  • 42
  • 41
-1
  1. Check whether your layout current one or old one for example

    setContentView(R.layout.activity_main);
    
  2. Delete old .gradle file in your project file and rebuild gradle file for project.

Balaji Bal
  • 60
  • 3