嵌套片段 - 非法状态异常“在 onSaveInstanceState 之后无法执行此操作”背景我的问题更新 2更新1:快速和肮脏(官方)解决方案我的解决方案结论
背景
安卓系统中的异步回调
尝试在Android上以可靠的方式执行异步操作是不必要的复杂,即AsyncTask是否真的在概念上存在缺陷,或者我只是错过了一些东西?
现在,这都是在引入碎片之前。随着 Fragments 的引入,onRetainNonConfigurationInstance() 已被弃用。因此,最新的Google纵容黑客攻击是使用持久的非UI片段,该片段在发生配置更改时(即旋转屏幕,更改语言设置等)从您的活动中附加/分离。
示例:https://code.google.com/p/android/issues/detail?id=23096#c4
非法状态异常 - 无法在 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);
}
}
因此,从理论上讲,现在您知道何时可以安全地执行片段交易,因此可以避免可怕的非法状态异常。
错!
嵌套片段
上述解决方案仅适用于活动的 FragmentManager。片段本身也有一个子片段管理器,用于嵌套片段。遗憾的是,子片段管理器根本没有与活动的片段管理器保持同步。因此,虽然活动的片段管理器是最新的,并且始终具有正确的mStateSaved;儿童碎片不这么认为,并且会很乐意在不适当的时间抛出可怕的非法状态异常。
现在,如果您已经查看了支持库中的 Fragment.java和 FragmentManager.java您不会对与片段相关的所有事情都容易出错感到惊讶。设计和代码质量是...啊,值得怀疑。你喜欢布尔值吗?
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
无论如何,有点偏离主题。
死胡同解决方案
因此,您可能会认为问题的解决方案很简单,在这一点上似乎有点反义词,将另一个漂亮的黑客非UI片段添加到您的子片段管理器中。据推测,它的回调与其内部状态同步,一切都会很花哨。
又错了!
Android 不支持作为子级附加到其他片段(也称为嵌套片段)的保留片段实例。现在,事后看来,这应该是有道理的。如果在活动因未保留而销毁父片段时销毁父片段,则无需重新附加子片段。所以这是行不通的。
我的问题
是否有人有解决方案来确定何时与异步代码回调一起对子片段执行片段事务是安全的?