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

    1. 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
    
        }
      }
    }

     

     

  • 相关阅读:
    数据压缩和归档
    数据持久化
    文件和目录的使用
    数据及数据处理
    data types
    string services
    logging模块
    指导
    比较两个NSDate类型的参数相差的时间差
    推送 iOS 10
  • 原文地址:https://www.cnblogs.com/renhui/p/6085202.html
Copyright © 2011-2022 走看看