Сбой сохранения состояния – цель не в менеджере фрагментов (setTargetFragment)

У меня крушение обезьяны, где

java.lang.IllegalStateException: Failure saving state: FragmentB has target not in fragment manager: FragmentA at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1561) at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:475) at com.acme.ParentActivity.onSaveInstanceState(Unknown Source) 

В основном FragmentA загружает FragmentB и setTargetFragment вызывается для установки целевого фрагмента FragmentB.

Затем FragmentB просто вызывает getTargetFragment в методе onCreate и зависает с целевым объектом в случае необходимости.

Теперь я ничего не делаю в любых onSaveInstanceState с целевым фрагментом с точки зрения установки его нулевого значения, делая любые saveFragmentInstanceState , putFragment и т. Д. Вопрос в том, должен ли я что-то делать с этим?

Заранее спасибо,

Питер.

** Редактирование 1 ** Я использую старую версию библиотеки поддержки и чувствую, что это может быть исправлено в последней версии, будет проверяться дальше и предоставить дополнительное обновление, если это так. Тем не менее, все еще интересно узнать, нужно ли мне что-либо делать с целевым фрагментом, который я сейчас не делаю.

** Редактировать 1 ** Исправлено с версией 8 библиотеки поддержки (не пробовали другие).

Solutions Collecting From Web of "Сбой сохранения состояния – цель не в менеджере фрагментов (setTargetFragment)"

На самом деле вам нужно сделать две вещи, чтобы решить эту проблему:

1. Убедитесь, что вы используете getChildFragmentManager () NOT getFragmentManager () при запуске FragmentB из FragmentA

Вызов getChildFragmentManager () вернет FragmentManager Fragment хостинга, тогда как getFragmentManager () вернет FragmentManager Activity Activity. Важно использовать getChildFragmentManager (), потому что вы размещаете фрагмент внутри другого фрагмента, поэтому родительский фрагмент должен отвечать за обработку любых транзакций с вложенным фрагментом. Если вы используете getFragmentManager (), вы столкнетесь с проблемой, с которой вы сейчас сталкиваетесь.

2. НЕ используйте setTargetFragment () и getTargetFragment (), они не будут работать при использовании getChildFragmentManager ()

Вместо этого используйте getParentFragment (). Я считаю, что есть некоторая ошибка в Android прямо сейчас, где даже если вы правильно звоните

fragmentB.setTargetFragment(fragmentA, 0);

А затем отобразить FragmentB, после изменения конфигурации вызов getTargetFragment () из FragmentB вернется непосредственно вместо FragmentA.

Вот обходной путь:

Поместите это в фрагмент, который вызывает проблемы:

 @Override public void onSaveInstanceState(final Bundle outState) { setTargetFragment(null, -1); ... 

И не забудьте установить его в реальный фрагмент цели, когда вам это нужно.

Недавно мы столкнулись с этой проблемой. Мы внедрили пользовательский адаптер, расширяющий android.support.v4.app. FragmentStatePagerAdapter . С android.support.v4.app. FragmentManager , мы создали несколько фрагментов в пейджере, а также несколько других фрагментов вне пейджера. Осколки управляются в одном действии. Есть несколько случаев, когда мы устанавливаем цель (с setTargetFragment ) фрагментов не-пейджинга на фрагменты, которые могут содержать или не содержать в пейджинговом адаптере. Поскольку FragmentStatePagerAdapter поддерживает только определенное количество фрагментов, фрагменты, которые были установлены в качестве целей и что FragmentStatePagerAdapter считается более не нужным, были уничтожены … и потенциально несогласованное состояние, если фрагменты, которые имели эти цели, все еще существуют. Это привело к тому, что исключение было выброшено всякий раз, когда приложение потеряло фокус (либо когда экран выключен, либо приложение зашло в фоновый режим), т. Е. Когда вызывается onSaveInstanceState .

Чтобы предотвратить это исключение, в onSaveInstanceState мы проверили, какие фрагменты были в настоящее время в диспетчере фрагментов. Если бы были какие-либо несоответствия (т. Е. Отсутствовал фрагмент «target»), мы удалили фрагмент, у которого был этот целевой набор. В нашем случае у нас было всего три фрагмента, где мы устанавливали цель, чтобы мы точно знали, что искать.

Я не верю, что есть какой-либо другой способ справиться с этим делом, но если у кого-нибудь будет какая-то полезная обратная связь, это будет очень признательно.

Убедитесь, что вы добавили оба фрагмента в стопку!

Я просто столкнулся с этой проблемой при добавлении нового «вызванного» фрагмента для результата поверх фрагмента «target». Первоначально я получал ту же ошибку, которая прекратилась, как только я добавил оба фрагмента в задний стек всякий раз, когда я их использовал.

Проблема возникла при поворотах экрана, поэтому ее было легко воспроизвести.

Было мало изменений относительно порядка жизненного цикла onSaveInstance () между Pre-HoneyComb и post-Honeycomb. Пожалуйста, обратитесь к этой статье для получения дополнительной информации:

http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

Я просто столкнулся с этой проблемой, и это то, что я думаю, происходит и как я ее исправил:

Экземпляр FragmentA уничтожается, а другой создается, например, при вращении устройства. Когда это произойдет, ваш FragmentB держит ссылку на FragmentA, который больше не существует.

В этом случае вам нужно сбросить цель FragmentB в качестве нового экземпляра FragmentA.

Я сделал это со следующим кодом в FragmentA:

 @Override public void onAttach(Context context) { super.onAttach(context); FragmentB fragment = (FragmentB) getFragmentManager().findFragmentByTag(FragmentBtag); if (fragment != null) { fragment.setTargetFragment(this, 0); } } 

Таким образом, всякий раз, когда FragmentA привязан к Контексту, т. Е. Происходит поворот устройства, цель FragmentB сбрасывается, если FragmentB был создан из первых рук (если это так, то это будет на FragmentManager).

Я надеюсь, что это помогает.

У меня была эта проблема при показе DialogFrament из другого фрагмента и использовании setTargetFragment в диалоговом окне DialogFragment. Проблема была решена с помощью getChildFragmentManager () при отображении DialogFragment.

  1. ActivityA добавил FragmentA
  2. FragmentA добавил DialogFragmentB с помощью FragmentManager ActivityA.
  3. Вызывается dialogFragmentB.setTargetFragment (фрагмент)
  4. Удалено FragmentA и добавлен новый экземпляр FragmentA
  5. FragmentManager, связанный с ActivityA, по-прежнему содержал DialogFragmentB, который имел первый экземпляр FragmentA в качестве целевого фрагмента.

Это вызвало исключение исключения «Недействительное состояние – цель не в диспетчере фрагментов».