出现异常:片段已激活

Posted

技术标签:

【中文标题】出现异常:片段已激活【英文标题】:Got exception: fragment already active 【发布时间】:2012-05-09 00:27:26 【问题描述】:

我有一个片段

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

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

【问题讨论】:

你的片段是单例吗?如果有的话,给我看看你的 newInstance() 方法。 我希望这对某人有所帮助。 ***.com/a/15263921/541620 ***.com/a/15263921/541620 我希望这可以帮助别人。 我希望这对某人有所帮助。 [这里][1] [1]:***.com/a/15263921/541620 【参考方案1】:

阅读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)。我猜你想要做的是创建一个 new Fragment 并再次设置参数。或者你可以使用getArguments(),然后使用bundle的put方法来改变它的值。

【讨论】:

+1 表示“你可以使用 getArguments() 然后使用 bundle 的 put 方法来改变它的值。” 这是一个很好的例子,也有详细的解释。 emuneee.com/blog/2013/01/07/saving-fragment-states getArguments().putAll(bundle); 将覆盖整个包 getArguments().putAll(bundle); 不会覆盖整个捆绑包。调用此键后,我仍然拥有以前的键和值。就我而言,我使用了 getArguments().clear(); 并清理了参数。 如果之前没有设置 setArguments(),则不能使用 getArguments().putAll(),因为 getArguments() 返回 null。【参考方案2】:

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

【讨论】:

我首先尝试了 "fragmentTransaction.remove(myFrag)" 然后 "replace(...)" ,它没有帮助。我有同样的例外 nono 以前的。所以堆栈上的任何东西都用 remove 删除,然后用 myfrag 替换。 fragmentTransaction.remove(myFrag) 从其addedFragment 堆栈中删除片段,但将其实例保留在其activeFragment 堆栈中。【参考方案3】:

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

fragmentTransaction.remove(activeFragment);

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

fragmentTransaction.remove(activeFragment).commit();

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

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

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

【讨论】:

【参考方案6】:

只需从片段中调用公共方法

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

【讨论】:

【参考方案7】:

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

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

总结一下,

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

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

【讨论】:

【参考方案8】:

    例如检查您的布局是当前的还是旧的

    setContentView(R.layout.activity_main);
    

    删除项目文件中的旧 .gradle 文件并为项目重建 gradle 文件。

【讨论】:

以上是关于出现异常:片段已激活的主要内容,如果未能解决你的问题,请参考以下文章

片段已激活 - 尝试 setArguments 时

活动到片段通信:当我尝试从活动更新片段中的文本视图时,出现空指针异常

以编程方式创建 MapView 并添加标记导致片段中出现空指针异常

片段中的 Listview 适配器给出空指针异常

mvn命令异常:An error has occurred in Javadoc report generation: Unable to find javadoc command异常已解决(代码片段

mvn命令异常:An error has occurred in Javadoc report generation: Unable to find javadoc command异常已解决(代码片段