58

我有一个片段

MyFragment myFrag = new MyFragment();

我将捆绑数据放入此片段:

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

然后,我用这个替换旧片段并放入 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();

稍后,我使用上面的事务 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

似乎即使我删除了片段,它仍然处于活动状态......为什么?如何停用片段?

4

8 回答 8

152

阅读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()然后使用bundle 的方法来改变它的值。 put

于 2013-02-26T08:41:42.263 回答
1

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

于 2012-04-28T15:05:36.607 回答
1

remove() 将片段状态更改为停用。在您的情况下,您只是在 remove(..) 之后没有调用 commit()。

fragmentTransaction.remove(activeFragment);

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

fragmentTransaction.remove(activeFragment).commit();
于 2014-11-20T11:08:24.313 回答
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();
                    }
                }
于 2016-11-22T11:25:12.940 回答
0

我在 Xamarin.android 上遇到了同样的问题。这是文档所说的。

这只能在片段附加到其活动之前调用

于 2016-09-29T16:48:36.727 回答
0

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

当 Android 从堆栈中删除片段但尚未完成删除时,会发生此问题。为了检查这一点,您可以使用isRemoving()片段的方法。如果false,即片段未激活,您可以继续使用 设置参数setArguments(bundle)。否则,您无法将参数设置为已经处于活动状态的片段,并且只能通过使用getArguments().putAll(bundle).

总结一下,

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

如果您想避免这种情况,即立即删除片段以便没有活动片段,您可能希望使用onBackPressed()in onBackStackChangedListener(),它将设置isRemoving()false

于 2017-08-30T00:40:27.140 回答
0

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

于 2016-04-25T08:31:31.180 回答
-1
  1. 例如,检查您的布局是当前布局还是旧布局

    setContentView(R.layout.activity_main);
    
  2. 删除项目文件中的旧 .gradle 文件并为项目重建 gradle 文件。

于 2018-08-24T05:07:50.527 回答