正常是通过调用碎片的空的构造方法来实例化一个碎片对象,但是这不利于同时管理一批碎片的情况,因为开闭原则的需要,正常的实例方法根本满足不了。
这里用的是instantiate
使用方法,通过传入不同的碎片类名实例化。
Fragment fragment = Fragment.instantiate(mContext,
newNav.getClx().getName(), null);
参数
1.上下文
2.碎片的类名,和碎片的实例一同被维护在某个类中
3.Bundle 你可以理解为arguments 就是你赋给碎片的标识 在导航栏中常见
源码
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);
}
}
首先碎片的实例化有一个缓存机制。
private static final SimpleArrayMap<String, Class<?>> sClassMap =
new SimpleArrayMap<String, Class<?>>();
缓存的是什么呢?缓存的是碎片的类。如果你之前实例化过这个碎片了,你的类就会被存到这个map中去,然后下一次你就不需要通过类名来找到这个类了。
下面的代码就是缓存过程,就是以空间换取时间
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);
}
而
clazz = context.getClassLoader().loadClass(fname);
这句话就是通过类名来取得类的方法。这就是一种反射机制,通过类名来取得类,再由类来实例化。
实例化
Fragment f = (Fragment)clazz.newInstance();
最后你的碎片标识
if (args != null) {
args.setClassLoader(f.getClass().getClassLoader());
f.mArguments = args;
}