Не удается сохранить вложенные фрагменты
Есть ли другой способ сохранения состояния вложенного фрагмента?
Или, если мы не должны этого делать, почему? Спасибо!
02-13 11:42:43.258: E/AndroidRuntime(7167): java.lang.IllegalStateException: Can't retain fragements that are nested in other fragments
02-13 11:42:43.258: E/AndroidRuntime(7167): at android.support.v4.app.Fragment.setRetainInstance(Fragment.java:742)
Ответы
Ответ 1
Вы можете использовать FragmentManager.saveFragmentInstanceState(Fragment)
для извлечения состояния фрагмента. Возвращаемое значение реализует Parcelable, поэтому вы можете поместить его в Bundle.
Для восстановления вы можете предоставить состояние после создания фрагмента с помощью Fragment.setInitialSavedState(Fragment.SavedState)
.
Ответ 2
Поскольку библиотека поддержки 20+ (https://code.google.com/p/android/issues/detail?id=74222), есть ошибка с возможностью восстановления экземпляров для дочерних фрагментов, есть исправление для нее - http://ideaventure.blogspot.com.au/2014/10/nested-retained-fragment-lost-state.html
Код с веб-страницы (добавьте это в свой родительский фрагмент) -
private FragmentManager childFragmentManager() {//!!!Use this instead of getFragmentManager, support library from 20+, has a bug that doesn't retain instance of nested fragments!!!!
if(mRetainedChildFragmentManager == null) {
mRetainedChildFragmentManager = getChildFragmentManager();
}
return mRetainedChildFragmentManager;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (mRetainedChildFragmentManager != null) {
//restore the last retained child fragment manager to the new
//created fragment
try {
Field childFMField = Fragment.class.getDeclaredField("mChildFragmentManager");
childFMField.setAccessible(true);
childFMField.set(this, mRetainedChildFragmentManager);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
Ответ 3
Проблема: mChildFrgamentManager
воссоздается (https://code.google.com/p/android/issues/detail?id=74222)
Обход проблемы: Сохранение mChildFrgamentManager
, если фрагмент имеет setRetainInstance(true)
:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (getRetainInstance()) {
if (mRetainedChildFragmentManager != null) {
try {
Field childFMField = Fragment.class.getDeclaredField("mChildFragmentManager");
childFMField.setAccessible(true);
childFMField.set(this, mRetainedChildFragmentManager);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
mRetainedChildFragmentManager = getChildFragmentManager();
}
}
}
Предупреждение: С этим кодом setRetainInstace
следует вызывать перед onAttach
.
P.S: Это немного улучшенная версия ответа @attels.
Ответ 4
Это больше не ограничение с последней библиотекой поддержки, после AOSP commit.
Ниже сообщение о фиксации:
Разрешить setRetainInstance (true) на вложенных фрагментах
Сохранение произвольно вложенных фрагментов в конфигурационных изменениях как объекты неконфигурации. Это позволяет использовать save-instance дочерние фрагменты как произвольные непрозрачные зависимости в других фрагменты.