52

我有一个片段;有异常:片段已激活

MyFragment myFrag = new MyFragment(); 

我把捆数据这个片段:

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

然后,我与穿上堆栈中这一个,更换旧片段:

//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(); 

后来,我流行backstack上述交易ID(transId):

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

后来,我再次设置捆数据作为参数传递给我的片段(myFrag):

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

正如你看到的,我上面的代码了例外Java.lang.IllegalStateException: fragment already active我不明白为什么myFrag仍然活跃,虽然我已经从后台弹出它的交易。,无论如何,因为我得到了例外,我想我没有选择,只能去积极的片段,所以我所做的:

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

我不知道如果我的上述代码确实可以非激活的片段,因为我没有找到如何去除一个片段。 :(

之后,当我尝试捆绑数据重新设置为我的片段myFrag,我还是得到了同样的错误:我删除片段

Java.lang.IllegalStateException: fragment already active 

似乎甚至,它仍然是积极的...... 为什么如何去活性片段

+1

你的片段是单身吗?如果有,请告诉我你的newInstance()方法。 – clauziere 2012-10-12 01:56:58

+0

我希望这可以帮助某人。 http://stackoverflow.com/a/15263921/541620 – theWook 2013-03-07 06:00:50

+0

http://stackoverflow.com/a/15263921/541620 我希望这可能有助于某人。 – theWook 2013-03-07 06:01:53

回答

1

尝试添加新的人之前删除以前的片段:https://stackoverflow.com/a/6266144/969325

+0

我试图首先 “fragmentTransaction.remove(myFrag)”,然后“替换(。 ..)“,它没有帮助。我得到了同样的例外 – 2012-04-28 15:09:42

+0

nono上一个。所以无论是在堆栈中删除与删除,然后你用myfrag替换。 – Warpzit 2012-04-28 15:45:53

+0

'fragmentTransaction.remove(myFrag)'将片段从其“addedFragment”堆栈中移除,但将其实例保留在其“activeFragment”堆栈中。 – DeltaCap 2014-12-09 11:34:08

134

setArguments(Bundle args)源将帮助你明白:

/** 
* 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; 
} 

你不能再在你的代码在同Fragment使用setArguments(Bundle args)。你想要做的是我想要创建一个新的Fragment并再次设置参数。或者,您可以使用getArguments(),然后使用该包的put方法更改其值。

+48

+1“你可以使用getArguments(),然后使用bundle的put方法来改变它的值。” – Saran 2013-08-28 13:54:58

+0

下面是详细解释的很好例子。 http://emuneee.com/blog/2013/01/07/saving-fragment-states/ – Hesam 2014-11-26 02:49:51

+21

'getArguments()。putAll(bundle);'将覆盖整个包 – DeltaCap 2014-12-09 11:53:47

1

remove()将片段状态更改为取消激活。在你的情况下,你在删除(..)后没有调用commit()。

fragmentTransaction.remove(activeFragment); 

你也可以在remove()之后执行commit()。

fragmentTransaction.remove(activeFragment).commit(); 
0

有同样的问题。我正在将这个片段添加到后台堆栈中。错误是因为我没有调用popbackstack()。使用popbackstack帮助我

0

我在Xamarin.android上遇到同样的问题。这是the documentation所说的。

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

0

刚刚从片段

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

首先我先说明为什么会这样调用公共方法,然后我就拿出我发现工作的解决方案......。

这个问题发生在Android是去除片段从堆栈,但尚未与移除完毕。为了检查这个,你可以使用片段的isRemoving()方法。如果false,即片段未处于活动状态,则可以继续使用setArguments(bundle)设置参数。否则,您无法将参数设置为已激活的片段,只能通过使用getArguments().putAll(bundle)来寻址相同的参数来覆盖它。

总之,

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

如果你想避免这种情况,即在一次所以没有活性片段删除片段,您可能希望在onBackStackChangedListener()使用onBackPressed(),这将设置isRemoving()false

+0

不能解决您的问题。 – abhishek 2018-01-22 09:49:34