一般情况下,没有这个空构造器也不会出什么大问题。但是当系统内存不足的情况下,app处于后台条件下,内存会被系统回收,这时用户将app切换到前台,系统会重新将之前回收的内容实例化回来。
这个过程是Android系统通过两个方法来实现的:
onSaveInstantceState();
onRestoreInstantceState();
第一个方法是系统要回收该界面(Activity、Fragment)时调用的方法,用于保存该(Activity、Fragment)的实例变量到外存。
第二个方法是系统恢复该(Activity、Fragment)时调用的方法,用于恢复之前被回收的(Activity、Fragment)实例。
好了系统UI的策略基本搞清楚了,现在解释为什么Fragment需要这么一个空构造器。
当app回到前台时,系统会调用Activity 的 onRestoreInstantceState();
Activity在实例化得时候,如果Activity是通过FragmentState来管理Fragment的,如果发现其中有Fragment,就会调用FragmentState的instantiate(),该方法的实现如下:
public Fragment instantiate(FragmentHostCallback host, Fragment parent) {
if (mInstance != null) {
return mInstance;
}
final Context context = host.getContext();
if (mArguments != null) {
mArguments.setClassLoader(context.getClassLoader());
}
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.mFragmentManager = host.mFragmentManager;
if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
"Instantiated fragment " + mInstance);
return mInstance;
}
好,追踪Fragment的instantiate方法:
public static Fragment instantiate(Context context, String fname, @Nullable 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;
} catch (ClassNotFoundException e) {
throw new InstantiationException("Unable to instantiate fragment " + fname
+ ": make sure class name exists, is public, and has an"
+ " empty constructor that is public", e);
} catch (java.lang.InstantiationException e) {
throw new InstantiationException("Unable to instantiate fragment " + fname
+ ": make sure class name exists, is public, and has an"
+ " empty constructor that is public", e);
} catch (IllegalAccessException e) {
throw new InstantiationException("Unable to instantiate fragment " + fname
+ ": make sure class name exists, is public, and has an"
+ " empty constructor that is public", e);
}
}
看到没最终调用该Fragment的Class类的newInstance方法,无参构造器。如果有要恢复的参数,会再次赋给mArguments。这点很重要,我之前一直在纠结如果有个无参构造器,那参数初始化的问题咋办。其实这个无参构造器系统只是用它来实例化而已!