Фон
Асинхронные обратные вызовы в Android
Попытка выполнить асинхронную операцию надежным образом на Android излишне запутана, т.е. Является ли AsyncTask действительно концептуально ошибочным или я что-то не хватает?
Теперь это все до введения Фрагментов. С введением фрагментов onRetainNonConfigurationInstance() устарел. Таким образом, последний взломанный Google взломам заключается в использовании постоянного фрагмента, отличного от UI, который прикрепляет/отключает вашу активность при изменении конфигурации (т.е. Вращение экрана, изменение языковых настроек и т.д.).
Пример: https://code.google.com/p/android/issues/detail?id=23096#c4
IllegalStateException - Не удается выполнить это действие после onSaveInstanceState
Теоретически взломать выше позволяет обойти ужасные:
IllegalStateException - "Can not perform this action after onSaveInstanceState"
потому что постоянный не-UI-фрагмент будет получать обратные вызовы для onViewStateRestored() (альтернативно onResume) и onSaveInstanceState() (альтернативно onPause). Как таковой вы можете узнать, когда состояние экземпляра сохраняется/восстанавливается. Это справедливый бит кода для чего-то такого простого, но, используя эти знания, вы можете поставить очередь своих асинхронных обратных вызовов до тех пор, пока у функции FragmentManager не будет установлена переменная mStateSaved до false.
mStateSaved - это переменная, которая в конечном счете несет ответственность за запуск этого исключения.
private void checkStateLoss() {
if (mStateSaved) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
}
Итак, теоретически, теперь вы знаете, когда безопасно выполнять транзакции фрагментов, и поэтому вы можете избежать опасного исключения IllegalStateException.
Неправильно!
Вложенные фрагменты
Решение выше работает только для Activity FragmentManager. У самих фрагментов также есть дочерний менеджер фрагментов, который используется для вложения фрагментов. К сожалению, администраторы дочерних фрагментов не синхронизируются с менеджером фрагментов активности вообще. Поэтому, пока менеджер фрагментов активности обновлен и всегда имеет правильный mStateSaved; дочерние фрагменты думают иначе и будут счастливо бросать страшное исключение IllegalStateException в неподходящее время.
Теперь, если вы посмотрели файлы Fragment.java и FragmentManager.java в библиотеке поддержки, вы никоим образом не удивляетесь, что все и что-то связанное с фрагментами подвержено ошибкам. Дизайн и качество кода... ах, сомнительно. Вам нравится booleans?
mHasMenu = false
mHidden = false
mInLayout = false
mIndex = 1
mFromLayout = false
mFragmentId = 0
mLoadersStarted = true
mMenuVisible = true
mNextAnim = 0
mDetached = false
mRemoving = false
mRestored = false
mResumed = true
mRetainInstance = true
mRetaining = false
mDeferStart = false
mContainerId = 0
mState = 5
mStateAfterAnimating = 0
mCheckedForLoaderManager = true
mCalled = true
mTargetIndex = -1
mTargetRequestCode = 0
mUserVisibleHint = true
mBackStackNesting = 0
mAdded = true
В любом случае, немного отвлечься от темы.
Мертвое решение
Итак, вы можете подумать, что решение проблемы просто, которое на данный момент похоже на антоним, добавить еще один из этих хороших хакерских фрагментов без интерфейса для ваших дочерних менеджеров фрагментов. Предположительно, его обратные вызовы синхронизируются со своим внутренним состоянием, и все будет денди.
Неправильно снова!
Android не поддерживает сохраненные экземпляры фрагментов, которые привязаны как дети к другим фрагментам (ака вложенные фрагменты). Теперь, задним числом это должно иметь смысл. Если родительский фрагмент уничтожается, когда действие уничтожается, потому что его не сохраняют, не следует привязывать дочерний фрагмент. Так что просто не собираюсь работать.
Мой вопрос
Есть ли у кого-нибудь решение для определения, когда безопасно выполнять транзакции фрагментов на дочерних фрагментах в сочетании с асинхронными обратными вызовами кода?