Android Fragment State Saving. 以及 Can not perform this action after onSaveInstanceState 异常.

来源:互联网 发布:安卓编程类游戏 编辑:程序博客网 时间:2024/06/16 17:58

  1. FragmentActivity的onSaveInstanceState(Bundle outState)会调用:
    mFragments.saveAllState(),其返回一个Parcelable对象,并会将此对象放在onSaveInstanceState提供的
    Bundle中,
    mFragments其实是一个FragmentManagerImpl<位于support v4的FragmentManager.java中>
  2. FragmentManagerImpl saveAllState()的流程:
    (1)execPendingActions() 将没有执行的Transaction执行,确保state是update-to-date的.
    (2)对于Android3.0 HC以上 >= 11, 会专门将mStateSaved设为true: 注释是这么说的
    对于HC及以上的版本, 会在pausing以后再进行save state, 而在之前的版本,则是在pausing之前进行的,
    这就带来一个问题,在pausing之后 stoppping之前,可能会有很多操作会改变fragment的state, 对于这些旧设备,
    是不能肯定的说,state是确实被正确的save了,但是呢,到了这份上也没办法,所以对于旧设备就由他去吧,但是新设备会通过mStateSaved做check,后面的一个异常就是这个check。
    (3)内部维护的一个Fragment列表,mActive. 如果发现mActive都没有,那么显然不需要save 什么 state,直接return.
    (4)创建一个FragmentState数组, 遍历mActive,如果Fragment确实存在且mIndex>=0有效,那么目前的Manager中就确实是
    有Fragment的,以该fragment作为参数构造一个FragmentState<已经得到了state>,并赋给相应的FragmentState数组,
    然后再做个判断,如果Fragment的state > ragment.INITIALIZIN并且FragmentState还没有 mSavedFragmentState,
    那么就为次FragmentState创建一个saveFragmentBasicState(Fragment),否则直接取Fragment的mSavedFragmentState即可,
    可以看出来,每个Fragment在创建出来的时候是没有FragmentState<一个bundle>的,在save的时候,如果没有,就会为其创建一个,并
    自己维护一个引用,以后再save state的时候,就可以直接save了. 构造出的FragmentState数组会保存到一个FragmentManagerState
    对象的mActive引用上。
    (5) 下一步是将自己内部的一个Int[]的mAdded保存的fragment的index重新保存到一个added里,并进一步存为到FragmentManagerState的
    mActive数组。
    (6) 一个BackStackState列表也被构造并根据FragmentManager的mBackStack进行设置,然后保存到一个FragmentManagerState中。
    (7) 最后返回之前构造的那个FragmentManagerState对象,可以看出,Fragment保存state的过程其实也听简单的,
    先把每个Fragment的state进行保存,然后保存FragmentManager本身的一些信息,最后把这些信息都保存到一个FragmentManagerState
    对象中,供以后的restore.
    restoreAllState()函数基本就是上面的逆过程,这也就是Fragment 自己的 onSave/RestoreInstanceState(bundle outState)的
    外部调用过程: saveAllState() -> saveFragmentBasicState(fragment) -> fragment.performSaveInstanceState(mStateBundle)
    -> onSaveInstanceState(Bundle outState).
    (8) checkStateLoss()在mStateSaved的情况下,会throw一个IllegalStateException:
    “Can not perform this action after onSaveInstanceState”, throw的原因结合(2)也可以得出: 在
    mStateSaved为true的情况下,Fragment以及FragmentManager的信息都已经被save 到bundle了,
    这时候不能再有其他可能改变Fragment state的操作,否则 最后restore出来的state信息会不一致,因此
    这里会抛一个异常告知这种操作的非法.
0 0