得到例外:片段已经激活

时间:2012-04-28 14:37:22

标签: android android-layout android-intent android-emulator android-fragments

我有片段;

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

稍后,我使用上述交易ID(transId 弹出Backstack

//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

似乎我删除了片段,它仍处于活动状态...... 为什么?如何取消激活片段?

8 个答案:

答案 0 :(得分:147)

阅读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;
}

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

答案 1 :(得分:1)

尝试删除之前的片段,然后再添加新片段:https://stackoverflow.com/a/6266144/969325

答案 2 :(得分:1)

remove()将片段状态更改为de-actiive。在你的情况下,你只是在删除(..)后没有调用commit()。

fragmentTransaction.remove(activeFragment);

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

fragmentTransaction.remove(activeFragment).commit();

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

  

只有在片段附加到其活动

之后才能调用此方法

答案 5 :(得分: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();
                    }
                }

答案 6 :(得分:0)

首先,我首先描述为什么会发生这种情况,然后我会提出我找到的解决方案......

当Android 从堆栈中删除片段但尚未完成删除时,会出现此问题。为了检查这一点,您可以使用片段的isRemoving()方法。如果false,即片段未激活,您可以继续使用setArguments(bundle)设置参数。否则,您不能为已经活动的片段设置参数,并且只能通过使用getArguments().putAll(bundle)寻址相同的参数来覆盖它。

总结一下,

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

如果你想避免这种情况,即一次删除片段以便没有活动片段,你可能想在onBackPressed()中使用onBackStackChangedListener(),这会将isRemoving()设置为false

答案 7 :(得分:-1)

  1. 检查您的布局是当前版本还是旧版本

    git push origin "branch name"
  2. 删除项目文件中的旧.gradle文件并为项目重建gradle文件。