android Fragment里的newInstance和构造函数

最近用android studio创建fragment时,总是默认会创建一个静态工厂函数

public static InstalledAppFragment newInstance() {
        InstalledAppFragment fragment = new InstalledAppFragment(String param1, String param2);
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

注释里还会提示用这个方法实例化一个fragment类,抛开设计模式之外的优势,推荐这个方法的原因是因为这个默认创建的方法里包含了保存参数这一步操作。

fragment.setArguments(args);

如果系统在重建Fragment时,只会调用默认构造函数,这样参数就会丢失了,例如在横竖屏切换时,Fragment会重建,这时,通过FragmentState进行初始化时,会传入参数值。

    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;
        }

在进入一步的初始化中会设置参数,如果没有保存的话这里就会出现参数丢失了。

 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);
        }
    }

推荐阅读更多精彩内容