Фрагмент уже добавлен IllegalStateException

Я использую этот метод в своем контейнере Activity, чтобы показать BFrag

public void showBFrag()
{
    // Start a new FragmentTransaction
    FragmentTransaction fragmentTransaction = mFragmentMgr.beginTransaction();

    if(mBFrag.isAdded())
    {
        Log.d(LOG_TAG, "Show() BFrag");
        fragmentTransaction.show(mBFrag);   
    }
    else
    {
        Log.d(LOG_TAG, "Replacing AFrag -> BFrag");
        fragmentTransaction.replace(R.id.operation_fragments_frame, mBFrag);
    }

    // Keep the transaction in the back stack so it will be reversed when backbutton is pressed
    fragmentTransaction.addToBackStack(null);

    // Commit transaction
    fragmentTransaction.commit();        
}

Я вызываю его из своего контейнера Activity; в первый раз:

  • попадает в оператор else, а mBFrag заменяет mAFrag.

Затем нажимаю кнопку возврата:

  • и операция выполняется в обратном порядке (отображается mAFrag, но .. удаляется ли mBFrag?).

Затем я снова иду вперед, вызывая showBFrag () из того же Activity:

  • и он СНОВА попадает в оператор else. (так что я могу сделать вывод, что mBFrag НЕ ДОБАВЛЯЕТСЯ)
  • но у меня есть фрагмент, который уже добавлен IllegalStateException ... (так почему он не попал в оператор if вместо этого?)

So:

  1. Почему метод isAdded () не возвращает TRUE, если я получаю уже добавленный фрагмент IllegalStateException?
  2. Удаляет ли операция popBackStack полностью ранее добавленные фрагменты?
  3. Какое поведение я неправильно понимаю?

РЕДАКТИРОВАТЬ: вот полная информация об исключении.

06-07 12:08:32.730: ERROR/AndroidRuntime(8576): java.lang.IllegalStateException: Fragment already added: BFrag{40b28158 id=0x7f0c0085}
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at android.app.BackStackRecord.doAddOp(BackStackRecord.java:322)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at android.app.BackStackRecord.replace(BackStackRecord.java:360)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at android.app.BackStackRecord.replace(BackStackRecord.java:352)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at myPackageName.containerActivity.showBFrag() // This line: "fragmentTransaction.replace(R.id.operation_fragments_frame, mBFrag);"

person Axel M. Garcia    schedule 06.06.2011    source источник
comment
Ваш фрагмент синглтон?   -  person clauziere    schedule 12.10.2012
comment
twitter.com/cstruter/status/900982307812724736   -  person cstruter    schedule 25.08.2017


Ответы (11)


В конце концов, моим обходным решением было выполнить remove () предыдущего фрагмента и добавить () новый. Хотя вот что метод replace () предназначался для этого.

Но я все еще гадаю, почему в этом случае не сработал метод replace (). Это действительно странно, и я хочу отбросить это потому, что я что-то неправильно понимаю или делаю что-то не так.

person Axel M. Garcia    schedule 07.06.2011
comment
@AMGG Мне было бы интересно узнать, тестировались ли вы с библиотекой совместимости и несовместимыми версиями и обнаружили ли это проблемой с обоими, поскольку я использую replace(...) с первой без проблем (с моим самым первым фрагментом, добавленным с add(...) . - person PJL; 07.06.2011
comment
@AMGG О, хорошо, я никогда раньше не пробовал вызывать remove, поскольку он говорит, что это то, что делает replace, рад, что он работает для вас, это в CPL или 3.0? - person Nathan Schwermann; 07.06.2011
comment
Нет, я НЕ использую CPL. Я использую платформу API Google 3.0 и уровень API 11. - person Axel M. Garcia; 08.06.2011
comment
@AMGG, @schwiz, это тоже ошибка в CPL. Проблема в BackStackRecord:popFromBackStack, где в OP_REPLACE действие присваивается переменной в фрагменте, который был удален, а не в том, который добавляется повторно. Я сообщу об ошибке, если никто не захочет это сделать. Кому-то нужно уточнить свой ответ, указав на то, что это обходной путь к ошибке, а не проблема с зависанием ссылки? Ура, ребята. - person PJL; 08.06.2011
comment
@PJL, @schwiz, спасибо за всю информацию. @PJL поделитесь ссылкой на отчет об ошибке, чтобы мы могли проголосовать за него. Между тем мой обходной путь работает нормально. Ваше здоровье. - person Axel M. Garcia; 08.06.2011
comment
@AMGG, @schwiz ссылка на отчет об ошибке. Проблема 17488. - person PJL; 08.06.2011
comment
Извините, ошибка уже существует, ссылка. Я проголосовал за это вместо этого. - person PJL; 08.06.2011
comment
Кто-нибудь нашел лучшее решение этой проблемы или использует remove (), а затем add () - единственное жизнеспособное решение прямо сейчас? - person Hank; 30.06.2011
comment
Вы сказали удалить предыдущий фрагмент, но как найти этот фрагмент? С помощью FragmentManager? - person Tsunaze; 01.07.2011
comment
@AMGG См. Мой связанный с этим вопрос: stackoverflow.com/questions / 24833912 / - person Dr.jacky; 19.07.2014
comment
Возможно, это применимо, но в моем приложении я обхожу обычное асинхронное поведение фрагмента, вызывая getFragmentManager (). ExecutePendingTransactions () сразу после обоих .remove () и .add (). - person Logic1; 26.12.2015

Если состояние активности уже было сохранено, вызывать фиксацию уже небезопасно. Вместо этого вы должны позвонить commitAllowingStateLoss(). Надеюсь это поможет!

Изменить: хорошо, я внимательно рассмотрел вашу проблему, проблема в том, что вы пытаетесь добавить фрагмент, который уже был добавлен. Даже если вы используете замену или удаление вызовов, вы не можете этого сделать. Единственное, что я нашел, - это создать новый экземпляр фрагмента и добавлять его каждый раз. После удаления или замены фрагмента лучше всего отбросить все ссылки на него, чтобы сборщик мусора позаботился о нем.

person Nathan Schwermann    schedule 06.06.2011
comment
Нет ничего, что указывало бы на то, что выполнять фиксацию небезопасно, и по опыту вы все равно получите другое исключение, если бы это было так. Насколько я понимаю, пользователь просто вернулся, нажав кнопку «Назад», а затем сделал выбор где-нибудь, чтобы снова загрузить фрагмент, как, скажем, в демонстрационном примере API FragmentStack от AndroidDevelopers. Я бы сравнил с этим примером, чтобы увидеть, в чем разница. - person PJL; 07.06.2011
comment
@PJL, по моему опыту, в этой ситуации возникает исключение IllegalStateException. - person Nathan Schwermann; 07.06.2011
comment
Извините, да, такое же исключение, но имелось в виду другое сообщение, например Невозможно выполнить это действие после onSaveInstanceState. Опять же, ничто не указывает на то, что вызов commit не сохраняется. - person PJL; 07.06.2011
comment
commitAllowingStateLoss () не решил эту проблему. Но хорошо об этом знать. Спасибо - person Axel M. Garcia; 07.06.2011
comment
@AMGG хорошо, извините за путаницу, см. Мой обновленный ответ. Я тоже столкнулся с этой проблемой. Не уверен, что это проблема с библиотекой совместимости или с фрагментами в целом. - person Nathan Schwermann; 07.06.2011

Возможно, это не связано напрямую с этой проблемой, но я также заметил, что установка перехода к FragmentTransaction вызовет исключение IllegalStateException, а не установка перехода - нет.

Вот ошибка для этой проблемы: http://code.google.com/p/android/issues/detail?id=25598

person Johan Paul    schedule 16.02.2012

Я использовал это:

if (getFragmentManager().findFragmentByTag(newFragment.getClass().getName()) != null) {
   transaction.remove(newFragment);
 }

и добавил фрагмент с

MyFragment frag = new MyFragment(); 
transaction.add(R.id.container, frag, MyFragment.class.getName())

MyFragment.class.getName() означает tag

person Nartus Team    schedule 09.06.2015

Проверьте, добавлен ли уже фрагмент или нет, используя метод fragment.isAdded () Замените или добавьте фрагмент соответственно

person Jiju Induchoodan    schedule 06.06.2014

попробуйте это после fragmentTransection.replace ()

fragmentTransection.addToBackStack(null);
fragmentTransection.commitAllowingStateLoss();
person Saleh Sheper    schedule 02.05.2015

Удаление setOffscreenPageLimit из Viewpager решило мою проблему. Спасибо.

person Pradeep Kumar Kushwaha    schedule 17.08.2016

Я попытался позвонить FragmentTransaction.remove() из onTabUnselected(), и это помогло обойти эту ошибку.

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    ft.add(R.id.fragment_container, fragment, null);
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    ft.remove(fragment);
}
person ObviousChild    schedule 11.03.2013

Этот код у меня работает нормально. попробуй это

((MiActivity)getActivity()).addAccount = new AddAccount();
((MiActivity)getActivity()).addAccount.setArguments(params);
fragmentManager = getActivity().getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container((MiActivity)getActivity()).addAccount);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
person Muhammad Aamir Ali    schedule 04.01.2014

Решил это, перебрав мои фрагменты и проверив, истинно ли isAdded (), а затем удалив этот фрагмент. Подробнее здесь.

person kylarsturn    schedule 29.09.2014

используйте список, сохраните экземпляр фрагмента и оцените это:

        if (!mFragmentTags.contains(fragTag + "")) {
                transaction.add(R.id.tab_main_container, mCurrentFragment, fragTag + "");
}

person litchi    schedule 17.01.2021