Android 有异常:片段已经激活

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10364478/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:26:11  来源:igfitidea点击:

Got exception: fragment already active

androidandroid-layoutandroid-intentandroid-emulatorandroid-fragments

提问by Leem.fin

I have a fragment;

我有一个片段

MyFragment myFrag = new MyFragment();

I put bundle datato this fragment:

我把捆绑数据放到这个片段中:

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

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

然后,我用这个替换旧片段并放在 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 backstackwith the above transaction ID(transId):

后来,我用上面的交易 ID( )弹出 backstacktransId

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

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

后来,我再次将捆绑数据设置为我的片段(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 whymyFragis 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:

如您所见,我上面的代码有异常Java.lang.IllegalStateException: fragment already active我不明白为什么myFrag尽管我已经从后台弹出了它的事务,但它仍然处于活动状态。,无论如何,因为我得到了异常,我认为我别无选择,只能停用片段,所以,我做到了:

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

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

我不确定我上面的代码是否真的可以停用片段,因为我没有找到如何停用片段。:(

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

之后,当我再次尝试将捆绑数据设置到我的片段myFrag时,我仍然遇到相同的错误:

Java.lang.IllegalStateException: fragment already active

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

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

回答by Assaf Gamliel

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

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

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 newFragmentand set the arguments again. Or you can use getArguments()and then use the putmethod of the bundle to change its values.

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

回答by Warpzit

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

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

回答by Dog??

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

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

fragmentTransaction.remove(activeFragment);

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

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

fragmentTransaction.remove(activeFragment).commit();

回答by Zhangali Bidaibekov

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

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

回答by Jonathan

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

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

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

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

回答by Krzysztof Dziuba

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

回答by Ali Nem

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 removingthe fragment from the stack but is not yetfinished 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).

当 Android从堆栈中删除片段但尚未完成删除时,会发生此问题。为了检查这一点,您可以使用isRemoving()片段的方法。如果false,即片段未激活,您可以继续使用 设置参数setArguments(bundle)。否则,您无法为已经激活的片段设置参数,只能通过使用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.

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

回答by Balaji Bal

  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.

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

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