zoukankan      html  css  js  c++  java
  • Android Fragment 使用技巧

    如果没有无参构造函数,而是像按照普通类来使用,只创建有参构造函数,则会出现 android.support.v4.app.Fragment$InstantiationException 错误。

    原因:Fragment 和 Activity 都是生命周期的组件,不能看做一般的类。如果非要使用有参构造函数,可能在使用的时候第一次传参没有问题,但是大概率在后面使用的时候出现问题。因为Fragment的什么周期依附在Activity中,如果Activity为null,那么Fragment肯定不能够正常使用了,比如手机屏幕的横竖屏切换导致Activity重建了。

    至于为什么是这样的呢?看下Fragment初始化的源码,有这么一段:

    复制代码
    /**
     * Create a new instance of a Fragment with the given class name.  This is
     * the same as calling its empty constructor.
     *
     * @param context The calling context being used to instantiate the fragment.
     * This is currently just used to get its ClassLoader.
     * @param fname The class name of the fragment to instantiate.
     * @param args Bundle of arguments to supply to the fragment, which it
     * can retrieve with {@link #getArguments()}.  May be null.
     * @return Returns a new fragment instance.
     * @throws InstantiationException If there is a failure in instantiating
     * the given fragment class.  This is a runtime exception; it is not
     * normally expected to happen.
     */
    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的创建其实也是利用了无参数的构造方法去实例化.但关键的是,它将Bundle传类新建的Fragment,这样旧的Fragment和新的Fragment就能拥有一样的Bundle,从而达到利用Bundle传递参数的目的. 

    查看Android的SDK文档,也给出来相关的说法:

    2. 给 Fragment 传递参数

    一定要使用 Bundle 方式传递参数,而不是通过重载构造函数传递参数。

    复制代码
    public static VechileFrag newInstance(Vehicle vehicle, String userId, boolean isAdd) {
        VechileFrag mf = new VechileFrag();
        Bundle args = new Bundle();
        args.putString("userId", userId);
        args.putBoolean("isAdd", isAdd);
        args.putParcelable("vehicle", vehicle);
        mf.setArguments(args);
        return mf;
    }
    
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle args = getArguments();
        if (args != null) {
            userId = args.getString("userId");
            isAdd = args.getBoolean("isAdd");
            vehicle = args.getParcelable("vehicle");
            if (vehicle == null) {
                vehicle = new Vehicle();
            }
        }
    }            
    复制代码

    3. Fragment 与 Activity 通信

    在 Fragment 中定义一个接口和要回调的方法, Activity实现Fragment接口,出国留学的条件需要时回调 Fragment 方法。

    复制代码
    public IVechile mIVechile;
      public interface IVechile {
      public void submitCarSuccess(String carId, String plateNo);
      }
      @Override
      public void onAttach(Activity activity) { 
        fueltypes = FuelType.getList(activity);
        try {
          mIVechile = (IVechile) activity;
        }
        catch (Exception e) {
        // TODO: handle exception
    
        }
      }
    }
    复制代码
  • 相关阅读:
    PAT (Advanced Level) 1114. Family Property (25)
    PAT (Advanced Level) 1113. Integer Set Partition (25)
    PAT (Advanced Level) 1112. Stucked Keyboard (20)
    PAT (Advanced Level) 1111. Online Map (30)
    PAT (Advanced Level) 1110. Complete Binary Tree (25)
    PAT (Advanced Level) 1109. Group Photo (25)
    PAT (Advanced Level) 1108. Finding Average (20)
    PAT (Advanced Level) 1107. Social Clusters (30)
    PAT (Advanced Level) 1106. Lowest Price in Supply Chain (25)
    PAT (Advanced Level) 1105. Spiral Matrix (25)
  • 原文地址:https://www.cnblogs.com/huilixieqi/p/6473577.html
Copyright © 2011-2022 走看看