天天看点

Android碎片实例化方法:instantiate的使用及其源码解析

正常是通过调用碎片的空的构造方法来实例化一个碎片对象,但是这不利于同时管理一批碎片的情况,因为开闭原则的需要,正常的实例方法根本满足不了。

这里用的是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;
}