本文主要分析两个问题
1, 自己写Fragment里面的普通成员变量会被“清理”,但是之前设置的arguments还在,调用getArguments()还能拿到数据。
2, FragmentAcitvity由于内存重启后,里面的Fragment是否是重新创建?
第一个问题:getArguments()为什么能拿到数据。
内存重启,会先调用FragmentAcitvity的onSaveInstanceState,保存fragment状态在mFragments.saveAllState()这行。
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Parcelable p = mFragments.saveAllState(); if (p != null) { outState.putParcelable(FRAGMENTS_TAG, p); } }
进入saveAllState()方法,下面代码最后两行,新建了一个FragmentState,用来保存Fragment数据
Parcelable saveAllState() { // First collect all active fragments. int N = mActive.size(); FragmentState[] active = new FragmentState[N]; boolean haveFragments = false; for (int i=0; i<N; i++) { Fragment f = mActive.get(i); if (f != null) { if (f.mIndex < 0) { throwException(new IllegalStateException( "Failure saving state: active " + f + " has cleared index: " + f.mIndex)); } haveFragments = true; FragmentState fs = new FragmentState(f); active[i] = fs;
再看FragmentState的构造函数,最后一行
public FragmentState(Fragment frag) { mClassName = frag.getClass().getName(); mIndex = frag.mIndex; mFromLayout = frag.mFromLayout; mFragmentId = frag.mFragmentId; mContainerId = frag.mContainerId; mTag = frag.mTag; mRetainInstance = frag.mRetainInstance; mDetached = frag.mDetached; mArguments = frag.mArguments; }
mArguments= frag.mArguments; 将Fragment的arguments进行了保存,所以回答了第一个问题。
最后所有数据通过FragmentManagerState进行保存
FragmentManagerState fms = new FragmentManagerState(); fms.mActive = active; fms.mAdded = added; fms.mBackStack = backStack;
并在 onSaveInstanceState 方法里,将数据存入Bundle
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Parcelable p = mFragments.saveAllState(); if (p != null) { outState.putParcelable(FRAGMENTS_TAG, p); } }
第二个问题:内存重启后,里面的Fragment是否是重新创建?
答案:重新创建。
首先进入FragmentActivity的onCreate,在Bundle里取出onSaveInstanceState中保存的数据,然后进行restoreAllState。
@Override protected void onCreate(Bundle savedInstanceState) { ………… if (savedInstanceState != null) { Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG); mFragments.restoreAllState(p, nc != null ? nc.fragments : null); } mFragments.dispatchCreate(); }
在restoreAllState里,通过FragmentState.instantiate进行创建
for (int i=0; i<fms.mActive.length; i++) { FragmentState fs = fms.mActive[i]; if (fs != null) { Fragment f = fs.instantiate(mActivity, mParent); if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f); mActive.add(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; } else { mActive.add(null); if (mAvailIndices == null) { mAvailIndices = new ArrayList<Integer>(); } if (DEBUG) Log.v(TAG, "restoreAllState: avail #" + i); mAvailIndices.add(i); } }
进入instantiate方法,下面代码最后一行
public Fragment instantiate(FragmentActivity activity, Fragment parent) { if (mInstance != null) { return mInstance; } if (mArguments != null) { mArguments.setClassLoader(activity.getClassLoader()); } mInstance = Fragment.instantiate(activity, mClassName, mArguments);
进入最后的Fragment.instantiate(activity, mClassName,mArguments);方法通过反射去创建。
public static Fragment instantiate(Context context, String fname, Bundle args) { try { Class<?> clazz = sClassMap.get(fname); if (clazz == null) { // Class not found in the cache, see if it's real, and try to add it clazz = context.getClassLoader().loadClass(fname); sClassMap.put(fname, clazz); } Fragment f = (Fragment)clazz.newInstance(); if (args != null) { args.setClassLoader(f.getClass().getClassLoader()); f.mArguments = args; } return f;
小结:内存重启,fragment的部分数据是通过FragmentActivity的onSaveInstanceState进行保存,并在OnCreate里进行恢复。由于mUserVisibleHint并没有在FragmentState里,所以如果不做好处理,会出现布局重叠。