Activity状态的死灰复燃和保留,设计格局备忘录方式

1.备忘录格局的概念及利用处境
备忘录格局是一种行为形式,该形式用于保存对象当前景色,并且在其后方可另行复苏到此景况。备忘录形式完成的办法索要确保被封存的靶子情况不能被对象从表面访问,目标是为了维护好被保存的那么些目的情状的完整性以及其中贯彻不向外揭露。
定义:
在不破坏封闭的前提下,捕获一个对象的里边意况,并在该对象之外保存那些场合,这样,将来就可将该对象回复到原来保存的情况
动用情状:

常见我们运用下边的章程保存Activity的情形

亟待保留一个目的在某一个整日的动静或一些情形
急需用一个接口来让别的对象获得那一个情形,将会揭露目的的兑现细节并破坏对象的封装性,一个对象不希望外面直接访问其中间景观,通过中间对象可以直接访问其里面情状

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}

Paste_Image.png

接下去大家从源码分析一下

2. 备忘录格局的利害
2.1优点
给用户提供了一种可以过来情形的体制,可以使用户可以相比便利地回来某个历史的图景
落到实处了音讯的包装,使得用户不需求关爱状态的保持细节
2.2缺点
费用资源,如果类的积极分子变量过多,势必会占用相比较大的资源,而且每三遍保存都会消耗一定的内存

protected void onSaveInstanceState(Bundle outState) {
//通告mWindow去保存层级状态
outState.putBundle(WINDOW_HIERARCHY_TAG,
mWindow.saveHierarchyState());
outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
//保存Fragment的状态
Parcelable p = mFragments.saveAllState();
if (p != null) {
//把数据放到Bundle里
outState.putParcelable(FRAGMENTS_TAG, p);
}
if (mAutoFillResetNeeded) {
outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
getAutofillManager().onSaveInstanceState(outState);
}
getApplication().dispatchActivitySaveInstanceState(this, outState);
}

3.注意事项

我们知晓mWindow是PhoneWindow的实例,下边去探访

备忘录的生命期备忘录创设出来就要在“近期”的代码中利用,要勇往直前管理它的生命周期,建立就要选用,不选用就要马上删除其引用,等待垃圾回收器对它的回收处理
备忘录的品质不要在一而再建立备份的气象中利用备忘录方式(比如一个for循环中),紧要缘由是一是控制不了备忘录建立的目的数量;而是大目的的建立是要成本资源的,系统的属性必要考虑。
4. 备忘录形式的落到实处格局

public Bundle saveHierarchyState() {
Bundle outState = new Bundle();
//mContentParent是DecorView中一个id为content的器皿,大家Activitiy中的布局
即便加上到这一个mContent中
if (mContentParent == null) {
return outState;
}
//创制一个容器,用来保存View层级结构
SparseArray<Parcelable> states = new
SparseArray<Parcelable>();
//保存View树状态
mContentParent.saveHierarchyState(states);
//将情形存到Bundle中
outState.putSparseParcelableArray(VIEWS_TAG, states);

public class Memento {
    //发起人的内部状态
    private String state="";
    public Memento(String state) {
        this.state = state;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
}```
           // 保存有焦点的View
           View focusedView = mContentParent.findFocus();
           if (focusedView != null) {
               if (focusedView.getId() != View.NO_ID) {
                   outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
               } else {
                   if (false) {
                       Log.d(TAG, "couldn't save which view has focus because the focused view "
                               + focusedView + " has no id.");
                   }
               }
           }
           return outState;
       }

public class Caretaker {
//备忘录对象
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}“`

接下去我们看saveHierarchyState方法,由于ViewGroup没这么些措施,所以大家去View里看

public class Originator {
    //内部状态
    private String state = "";
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    //创建一个备忘录
    public Memento createMemento() {
        return new Memento(state);
    }
    //恢复一个备忘录
    public void restoreMemento(Memento memento) {
        this.setState(memento.getState());
    }
}```

public void saveHierarchyState(SparseArray<Parcelable> container)
{
dispatchSaveInstanceState(container);
}

public class Test {
public static void main(String args[]) {
//定义出发起人
Originator originator = new Originator();
originator.setState(“初始:1111111111111”);
//定义出备忘录管理员
Caretaker caretaker = new Caretaker();
System.out.println(originator.getState());
//创设一个备忘录
caretaker.setMemento(originator.createMemento());
originator.setState(“改变:22222222222222”);
System.out.println(originator.getState());
originator.setState(“恢复:restoreMemento”);
originator.restoreMemento(caretaker.getMemento());
System.out.println(originator.getState());
}
}“`
5. 备忘录格局在Android中的实际运用
在Android开发中,状态方式应用是Android中的状态保持,也就是其中的onSaveInstanceState和onRestoreInstanceState。当Activity不是例行方式退出,且Activity在跟着的岁月内被系统杀死此前会调用那三个法子让开发人士可以有机遇存储Activity的连锁新闻,并且在下次放好Activity的时候复苏那个多少。
Activity:

protected void dispatchSaveInstanceState(SparseArray<Parcelable>
container) {
//判断View是还是不是有id以及是或不是允许保留
if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
//获取保存的结果
Parcelable state = onSaveInstanceState();
if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
throw new IllegalStateException(
“Derived class did not call super.onSaveInstanceState()”);
}
if (state != null) {
// Log.i(“View”, “Freezing #” + Integer.toHexString(mID)
// + “: ” + state);
//把结过放到容器中,键为View的id,值为状态
container.put(mID, state);
}
}
}

protected void onSaveInstanceState(Bundle outState) {
 outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState()); //保存当前窗口的视图树的状态
 Parcelable p = mFragments.saveAllState(); //存储Fragment的状态
 if (p != null) {
 outState.putParcelable(FRAGMENTS_TAG, p);
 }
 getApplication().dispatchActivitySaveInstanceState(this, outState);
 }```
Window的实现为PhoneWindow:

从地点的代码可以见到,一个View若是想要保存意况,则必须提供一个id,并且它是允许状态保存的,大家得以经过setSaveEnabled方法来决定是不是可以保留

/** {@inheritDoc} */
@Override
public Bundle saveHierarchyState() {
Bundle outState = new Bundle();
if (mContentParent == null) {
return outState;
}
//通过SparseArray类来存储,这一定于一个key为整型的map
SparseArray<Parcelable> states = new
SparseArray<Parcelable>();
//mContentParent就是调用Activity的setContentView函数设置的内容视图,它是内容视图的根节点,在这边存储整棵树的协会
mContentParent.saveHierarchyState(states);
//将视图树结构放到outState中
outState.putSparseParcelableArray(VIEWS_TAG, states);
// 保存当前界面中获取了要害的View
View focusedView = mContentParent.findFocus();
if (focusedView != null) {
if (focusedView.getId() != View.NO_ID) {
outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
} else {
if (false) {
Log.d(TAG, “couldn’t save which view has focus because the focused view

接下去大家看看ViewGroup的dispatchSaveInstanceState方法

  • focusedView + ” has no id.”);
    }
    }
    }
    // 存储整个面板的情状
    SparseArray<Parcelable> panelStates = new
    SparseArray<Parcelable>();
    savePanelState(panelStates);
    if (panelStates.size() > 0) {
    outState.putSparseParcelableArray(PANELS_TAG, panelStates);
    }
    //存储actionBar的状态
    if (mDecorContentParent != null) {
    SparseArray<Parcelable> actionBarStates = new
    SparseArray<Parcelable>();
    mDecorContentParent.saveToolbarHierarchyState(actionBarStates);
    outState.putSparseParcelableArray(ACTION_BAR_TAG,
    actionBarStates);
    }
    return outState;
    }“`
    在saveHierarchyState函数中,紧即使储存了与当下UI、ActionBar相关的View状态。mContentParent就是我们通过Activity的setContentView函数设置的内容视图,他是其一情节视图的根节点。mContentParent是一个ViewGroup对象,不过saveHierachyState是在父类View中

@Override
protected void dispatchSaveInstanceState(SparseArray<Parcelable>
container) {
super.dispatchSaveInstanceState(container);
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
View c = children[i];
if ((c.mViewFlags & PARENT_SAVE_DISABLED_MASK) !=
PARENT_SAVE_DISABLED) {
//保存每个子View的气象
c.dispatchSaveInstanceState(container);
}
}
}

到此,整个View的保留情况就完了,接下去自己i们看看Fragment的保存

public void saveHierarchyState(SparseArray<Parcelable> container) {
 dispatchSaveInstanceState(container);
 }```

Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}

protected void dispatchSaveInstanceState(SparseArray<Parcelable>
container) {
if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
Parcelable state = onSaveInstanceState();
if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
throw new IllegalStateException(
“Derived class did not call super.onSaveInstanceState()”);
}
if (state != null) {
// Log.i(“View”, “Freezing #” + Integer.toHexString(mID)
// + “: ” + state);
container.put(mID, state); //将自身意况放到container中 key 为id
value为我状态
}
}
}“`

说到底调用到了FragmentManagerImpl的saveAllState方法,,
下边是精简后的代码

//View类默认的存储的状态为空
 protected Parcelable onSaveInstanceState() {
  mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
  if (mStartActivityRequestWho != null) {
  BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
  state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
  return state;
  }
  return BaseSavedState.EMPTY_STATE;
  }```

恢复数据的调用过程如下,基本流程与保存类似
Activity:
    if (mActive == null || mActive.size() <= 0) {
        return null;
    }

    //获得当前活动中的Fragment
    int N = mActive.size();

protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (mWindow != null) {
Bundle windowState =
savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
if (windowState != null) {
mWindow.restoreHierarchyState(windowState);
}
}
}“`
PhoneWindow:

//创建对应的Fragment状态数据
FragmentState[] active = new FragmentState[N];
boolean haveFragments = false;
for (int i=0; i<N; i++) {
//获取活动中的每个Fragment
Fragment f = mActive.valueAt(i);
if (f != null) {
if (f.mIndex < 0) {
throwException(new IllegalStateException(
“Failure saving state: active ” + f

/** {@inheritDoc} */
 @Override
 public void restoreHierarchyState(Bundle savedInstanceState) {
 if (mContentParent == null) {
 return;
 }
 SparseArray<Parcelable> savedStates
 = savedInstanceState.getSparseParcelableArray(VIEWS_TAG);
 if (savedStates != null) {
 mContentParent.restoreHierarchyState(savedStates);
 }
 // restore the focused view
 int focusedViewId = savedInstanceState.getInt(FOCUSED_ID_TAG, View.NO_ID);
 if (focusedViewId != View.NO_ID) {
 View needsFocus = mContentParent.findViewById(focusedViewId);
 if (needsFocus != null) {
 needsFocus.requestFocus();
 } else {
 Log.w(TAG,
 "Previously focused view reported id " + focusedViewId
 + " during save, but can't be found during restore.");
 }
 }
 // restore the panels
 SparseArray<Parcelable> panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG);
 if (panelStates != null) {
 restorePanelState(panelStates);
 }
 if (mDecorContentParent != null) {
 SparseArray<Parcelable> actionBarStates =
 savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);
 if (actionBarStates != null) {
 doPendingInvalidatePanelMenu();
 mDecorContentParent.restoreToolbarHierarchyState(actionBarStates);
 } else {
 Log.w(TAG, "Missing saved instance states for action bar views! " +
 "State will not be restored.");
 }
 }
 }```
View:
  • ” has cleared index: ” + f.mIndex));
    }

              haveFragments = true;
              //创建每个Fragment对应的状态对象FragmentState 
              FragmentState fs = new FragmentState(f);
              active[i] = fs;
    
              if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
                //代码1
                  fs.mSavedFragmentState = saveFragmentBasicState(f);
    
                  if (f.mTarget != null) {
                      if (f.mTarget.mIndex < 0) {
                          throwException(new IllegalStateException(
                                  "Failure saving state: " + f
                                  + " has target not in fragment manager: " + f.mTarget));
                      }
                      if (fs.mSavedFragmentState == null) {
                          fs.mSavedFragmentState = new Bundle();
                      }
                      putFragment(fs.mSavedFragmentState,
                              FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
                      if (f.mTargetRequestCode != 0) {
                          fs.mSavedFragmentState.putInt(
                                  FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
                                  f.mTargetRequestCode);
                      }
                  }
    
              } else {
                  fs.mSavedFragmentState = f.mSavedFragmentState;
              }
    
              if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
                      + fs.mSavedFragmentState);
          }
      }
    

public void restoreHierarchyState(SparseArray<Parcelable>
container) {
dispatchRestoreInstanceState(container);
}“`

在代码1处,把saveFragmentBasicState方法的再次回到值给了FragmentState对象的
mSavedFragmentState属性,这一个特性是一个Bundle对象,上面我们看看saveFragmentBasicState方法

/**
* Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
* state for this view and its children. May be overridden to modify how restoring
* happens to a view's children; for example, some views may want to not store state
* for their children.
*
* @param container The SparseArray which holds previously saved state.
*
* @see #dispatchSaveInstanceState(android.util.SparseArray)
* @see #restoreHierarchyState(android.util.SparseArray)
* @see #onRestoreInstanceState(android.os.Parcelable)
*/
protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
if (mID != NO_ID) {
Parcelable state = container.get(mID);
if (state != null) {
// Log.i("View", "Restoreing #" + Integer.toHexString(mID)
// + ": " + state);
mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
onRestoreInstanceState(state);
if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
throw new IllegalStateException(
"Derived class did not call super.onRestoreInstanceState()");
}
}
}
}```

Bundle saveFragmentBasicState(Fragment f) {
Bundle result = null;

protected void onRestoreInstanceState(Parcelable state) {
mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
if (state != null && !(state instanceof AbsSavedState)) {
throw new IllegalArgumentException(“Wrong state class, expecting View
State but “

    if (mStateBundle == null) {
        mStateBundle = new Bundle();
    }
  • “received ” + state.getClass().toString() + ” instead. This usually
    happens “
  • “when two views of different type have the same id in the same
    hierarchy. “
  • “This view’s id is ” + ViewDebug.resolveId(mContext, getId()) + “.
    Make sure “
  • “other views do not use the same id.”);
    }
    if (state != null && state instanceof BaseSavedState) {
    mStartActivityRequestWho = ((BaseSavedState)
    state).mStartActivityRequestWhoSaved;
    }
    }“`
    在那几个进度中,Activity扮演了Caretaker角色,负责储存、恢复生机UI的情景音信;Activity、Fragement、View、ViewGroup等目的为Originator角色,也就是索要存储状态的目的;Memento则是由Bundle类扮演。

//代码2,调用Fragment对象的performSaveInstanceState方法
f.performSaveInstanceState(mStateBundle);
dispatchOnFragmentSaveInstanceState(f, mStateBundle, false);
if (!mStateBundle.isEmpty()) {
result = mStateBundle;
mStateBundle = null;
}

Activity在终止之前会根据Activity的退出情景来抉择是或不是须求存储状态,在重新启航该Activity时会判断ActivityClientRecord对象中是还是不是存储了Activity的事态,假若带有状态则调用Activity的onRestoreInstanceState函数,从而使得Activity的UI效果与上次保持一致,那样一来,就保证了在狼狈退出Activity时不会丢掉数据的情形,很好地升级了用户体验。
出处:http://huangjunbin.com/page/2/

    if (f.mView != null) {

//保存Fragment视图数结构
saveFragmentViewState(f);
}
if (f.mSavedViewState != null) {
if (result == null) {
result = new Bundle();
}
//将方面保存的视图树的结果放到Bundle中
result.putSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
}
if (!f.mUserVisibleHint) {
if (result == null) {
result = new Bundle();
}
// Only add this if it’s not the default value
result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG,
f.mUserVisibleHint);
}

    return result;
}

代码2处条用了Fragment的一个措施,如下

void performSaveInstanceState(Bundle outState) {

//执行Fragment的onSaveInstanceState方法,那是一个空方法
onSaveInstanceState(outState);
if (mChildFragmentManager != null) {
Parcelable p = mChildFragmentManager.saveAllState();
if (p != null) {
outState.putParcelable(FragmentActivity.FRAGMENTS_TAG, p);
}
}
}

上边大家看保存Fragment视图数结构的代码

void saveFragmentViewState(Fragment f) {
if (f.mView == null) {
return;
}
if (mStateArray == null) {
mStateArray = new SparseArray<Parcelable>();
} else {
mStateArray.clear();
}
//和方面View的保存情状同样
f.mView.saveHierarchyState(mStateArray);
if (mStateArray.size() > 0) {
f.mSavedViewState = mStateArray;
mStateArray = null;
}
}

总结

通过上面的分析,大家发现在saveFragmentBasicState中首要做了两件事,
1.保存Fragment的数据
2.保存Fragment视图树结构

然后把那几个数量给了FragmentState的一个Bundle属性,所以FragmentState那几个目的对Fragment的情事保存很重大。

景况上涨源码分析

我们看Activity的onRestoreInstanceState方法

protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (mWindow != null) {
//获取保存的视图树音信
Bundle windowState =
savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
if (windowState != null) {

//调用PhoneWindow的restoreHierarchyState方法
mWindow.restoreHierarchyState(windowState);
}
}
}

PhoneWindow的方法
@Override
public void restoreHierarchyState(Bundle savedInstanceState) {
if (mContentParent == null) {
return;
}
//获取保存的场合消息
SparseArray<Parcelable> savedStates
= savedInstanceState.getSparseParcelableArray(VIEWS_TAG);
if (savedStates != null) {
mContentParent.restoreHierarchyState(savedStates);
}

    // restore the focused view
    int focusedViewId = savedInstanceState.getInt(FOCUSED_ID_TAG, View.NO_ID);
    if (focusedViewId != View.NO_ID) {
        View needsFocus = mContentParent.findViewById(focusedViewId);
        if (needsFocus != null) {
            needsFocus.requestFocus();
        } else {
            Log.w(TAG,
                    "Previously focused view reported id " + focusedViewId
                            + " during save, but can't be found during restore.");
        }
    }

调用了View的方法

public void restoreHierarchyState(SparseArray<Parcelable>
container) {
dispatchRestoreInstanceState(container);
}

protected void
dispatchRestoreInstanceState(SparseArray<Parcelable> container)
{
//判断当前View是不是有id
if (mID != NO_ID) {
//依据id获取相应的数据
Parcelable state = container.get(mID);
if (state != null) {
// Log.i(“View”, “Restoreing #” + Integer.toHexString(mID)
// + “: ” + state);
mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
//恢复生机数据
onRestoreInstanceState(state);
if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
throw new IllegalStateException(
“Derived class did not call super.onRestoreInstanceState()”);
}
}
}
}

回复Fragment状态,我们看看Activity的onCreate方法
protected void onCreate(@Nullable Bundle savedInstanceState) {

if (savedInstanceState != null) {
//获取Fragment的数据
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.fragments : null);
}
mFragments.dispatchCreate();
getApplication().dispatchActivityCreated(this, savedInstanceState);

上面大家看看restoreAllState方法,这一个格局定义在FragmentManager中

void restoreAllState(Parcelable state, FragmentManagerNonConfig
nonConfig) {
if (state == null) return;
FragmentManagerState fms = (FragmentManagerState)state;
if (fms.mActive == null) return;

for (int i=0; i<fms.mActive.length; i++) {
//获取Fragment的情况数据
FragmentState fs = fms.mActive[i];
Fragment f = fs.instantiate(mHost, mContainer, mParent,
childNonConfig);
if (DEBUG) Log.v(TAG, “restoreAllState: active #” + i + “: ” + f);
mActive.put(f.mIndex, f);
// Now that the fragment is instantiated (or came from being
// retained above), clear mInstance in case we end up re-restoring
// from this FragmentState again.
fs.mInstance = null;
}

俺们去看FragmentState的instantiate方法

public Fragment instantiate(FragmentHostCallback host, FragmentContainer
container,
Fragment parent, FragmentManagerNonConfig childNonConfig) {
if (mInstance == null) {
final Context context = host.getContext();
if (mArguments != null) {
mArguments.setClassLoader(context.getClassLoader());
}

        if (container != null) {
            mInstance = container.instantiate(context, mClassName, mArguments);
        } else {
        //初始化Fragment
            mInstance = Fragment.instantiate(context, mClassName, mArguments);
        }
    //把之前保存的状态信息赋值给新建的对象
        if (mSavedFragmentState != null) {
            mSavedFragmentState.setClassLoader(context.getClassLoader());
            mInstance.mSavedFragmentState = mSavedFragmentState;
        }
        mInstance.setIndex(mIndex, parent);
        mInstance.mFromLayout = mFromLayout;
        mInstance.mRestored = true;
        mInstance.mFragmentId = mFragmentId;
        mInstance.mContainerId = mContainerId;
        mInstance.mTag = mTag;
        mInstance.mRetainInstance = mRetainInstance;
        mInstance.mDetached = mDetached;
        mInstance.mHidden = mHidden;
        mInstance.mFragmentManager = host.mFragmentManager;
        if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
                "Instantiated fragment " + mInstance);
    }
    mInstance.mChildNonConfig = childNonConfig;
    return mInstance;
}

此处只是恢复了Fragment的一部分的多寡,View视图树还没创制,所以其余数据是在Fragment进入生命周期才过来的,大家再再次来到Activity的onCreate中,调用了
mFragments.dispatchCreate();方法,此时调用的是FragmentManager的方法

public void dispatchCreate() {
mStateSaved = false;
dispatchMoveToState(Fragment.CREATED);
}

private void dispatchMoveToState(int state) {
if (mAllowOldReentrantBehavior) {
moveToState(state, false);
} else {
try {
mExecutingActions = true;
moveToState(state, false);
} finally {
mExecutingActions = false;
}
}
execPendingActions();
}

然后看moveToState方法
void moveToState(int newState, boolean always) {
if (mAdded != null) {
final int numAdded = mAdded.size();
for (int i = 0; i < numAdded; i++) {
Fragment f = mAdded.get(i);
//看此办法
moveFragmentToExpectedState(f);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
}

void moveFragmentToExpectedState(final Fragment f) {
if (f == null) {
ca88官方会员登录,return;
}
int nextState = mCurState;
if (f.mRemoving) {
if (f.isInBackStack()) {
nextState = Math.min(nextState, Fragment.CREATED);
} else {
nextState = Math.min(nextState, Fragment.INITIALIZING);
}
}
//看此形式
moveToState(f, nextState, f.getNextTransition(),
f.getNextTransitionStyle(), false);

在moveToState方法里调用了下边的法门
//调用Fragment的onActivityCreated方法
f.performActivityCreated(f.mSavedFragmentState);
dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
//苏醒Fragment视图状态
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}

从上边的代码大家得以见见,苏醒Fragment视图数据的时机是在onActivityCreated方法之后,

final void restoreViewState(Bundle savedInstanceState) {
if (mSavedViewState != null) {
//恢复View树状态
mView.restoreHierarchyState(mSavedViewState);
mSavedViewState = null;
}
mCalled = false;
onViewStateRestored(savedInstanceState);
if (!mCalled) {
throw new SuperNotCalledException(“Fragment ” + this

  • ” did not call through to super.onViewStateRestored()”);
    }
    }

@CallSuper
public void onViewStateRestored(Bundle savedInstanceState) {
mCalled = true;
}

总结

在Fragment中大家得以经过onSaveInstanceState方法保存数据,需求小心的是,Fragment并从未onRestoreInStanceState方法,大家一般重写onViewStateRestored方法苏醒数据

相关文章

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图