当布局不为空时,得到“java.lang.IllegalStateException:片段已处于活动状态”

时间:2014-02-16 11:56:26

标签: android android-fragments

我有3个片段的活动和寻呼机。我使用标签进行切换。 当我点击某个按钮时,我想用新的替换fragment0。 仅当fragment0具有空布局时才有效。如果我在fragment0的布局中设置了一些内容(必须有listview)抛出异常:

java.lang.IllegalStateException: Fragment already active
    at android.support.v4.app.Fragment.setInitialSavedState(Fragment.java:503)
    at android.support.v4.app.FragmentStatePagerAdapter.instantiateItem(FragmentStatePagerAdapter.java:110)
    at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:649)

我使用以下布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:id="@+id/all_exp_frag"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent">

<ListView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/all_expenses"/>

</LinearLayout>

的活动:

public class Activity extends FragmentActivity {

    private List<Fragment> fragments;
    private MyPagerAdapter pagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        fragments = asList(new Fragment0(), new Fragment1(), new Fragment2());
        // initialize pager, etc.
        pagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), pager);
    }

    // handle add new fragment button
    @Override
    public boolean onOptionsItemSelected(MenuItem item) { 
        pagerAdapter.replaceCurrentFragment(new Fragment3());
    }

    public class MyPagerAdapter extends FragmentStatePagerAdapter {

        final ViewPager pager;

        public MyPagerAdapter(FragmentManager fm, ViewPager pager) {
            super(fm);
            this.pager = pager;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return fragments.get(position).getFragmentTitle();
        }

        @Override
        public int getCount() {
            return fragments.size();
        }

        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }

        @Override
        public int getItemPosition(Object object) {
            if (object instanceof ExpensesFragment) {
                return POSITION_NONE;
            }
            return POSITION_UNCHANGED;
        }

        public void replaceCurrentFragment(BaseFragment fragment) {
            final int currentPosition = pager.getCurrentItem();
            final BaseFragment old_fragment = fragments.get(currentPosition);
            if (old_fragment == null) {
                return;
            }
            this.startUpdate(pager);
            getSupportFragmentManager()
                    .beginTransaction()
                    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .remove(old_fragment)
                    .add(pager.getId(), fragment)
                    .commitAllowingStateLoss();
            fragments.set(currentPosition, fragment);
            this.finishUpdate(pager);
            this.notifyDataSetChanged(); //IN THIS LINE EXCEPTION IS THROWN WHEN LAYOUT IS NOT EMPTY (contains listview). IF EMPTY - IT WORKS FINE.
            listener.onPageSelected(0);
        }

    }
}

应用程序在行上抛出异常

this.notifyDataSetChanged();

如果布局不为空。

我找不到解决方法如何避免此异常并正确替换片段。

EDITED

https://android.googlesource.com/platform/frameworks/support/+/jb-mr1-dev/v4/java/android/support/v4/app/Fragment.java

因为我检查了Fragment类包含以下方法:

public void setArguments(Bundle args) {
    if (mIndex >= 0) {
        throw new IllegalStateException("Fragment already active");
    }
    mArguments = args;
}

也许我添加片段的方式不正确..

2 个答案:

答案 0 :(得分:3)

添加片段的逻辑错误。可以在这里找到好的工作解决方案:correct answer

答案 1 :(得分:1)

使用片段类&#39;检查片段是否已添加。 #isAdded()方法。然后相应地替换或添加片段:

我们假设您的片段名为fragment

// Fragment object
Fragment fragment;

// Check to see if it's added or not like this
if (!fragment.isAdded()) {
    // Things you could do here:
    // -- Set argument
    // -- Begin a transaction 
    // -- etc...  
}