17

查看 的文档DialogFragment可以看到newInstance初始化新警报对话框片段的静态方法。我的问题是,为什么不使用构造函数来这样做,如下所示:

public MyAlertDialogFragment(int title) {
    Bundle args = new Bundle();
    args.putInt("title", title);
    setArguments(args);
}

这不是完全相同还是有所不同?什么是最好的方法,为什么

4

4 回答 4

28

如果你创建一个通过构造函数接收对象的DialogFragment,那么在android重新创建你的fragment时就会出现问题。这将发生:

  1. 您的代码会创建对话框,调用您创建的构造函数并将一些参数作为依赖项传递。
  2. 您的对话框运行,并使用您通过构造函数传递的依赖项
  3. 用户关闭应用
  4. 时间流逝,android杀死片段以释放内存
  5. 用户再次打开应用
  6. android 将使用默认构造函数重新创建您的对话框。不会传递任何参数!
  7. 您的对话框将处于不希望的状态。它可能会尝试使用您希望通过构造函数传递的实例变量,但由于它们不存在,您将获得空指针异常。

为了避免这种情况,您不需要依赖构造函数来建立依赖关系,而是在 Bundles 中(参数和保存的实例)。这可能会迫使您在某些类中实现 Parcelable,这很糟糕。

编辑:您可以通过在开发设置中启用“不维护活动”来重现 Android 杀死应用程序(第 4 步)。这是轻松测试它的方法。

于 2014-01-06T15:55:11.130 回答
20

Android 依赖于具有公共、零参数构造函数的 Fragments,以便它可以在不同时间重新创建它(例如,配置更改、在之前被 Android 杀死后恢复应用程序状态等)。

如果您没有这样的构造函数(例如问题中的构造函数),当它尝试实例化一个构造函数时,您将看到此错误:

Fragment$InstantiationException: Unable to instantiate fragment 
make sure class name exists, is public, and has an empty constructor that is public

提供给它的参数Fragment.setArguments(Bundle)将为您保存并提供给任何(重新)创建的新实例。使用静态方法创建片段只是提供了一种简单的方法来设置所需的参数,同时维护一个零参数的构造函数。

于 2012-12-23T14:46:11.107 回答
11

如果你用 重载了构造函数,如果需要重新创建,MyAlertDialogFragment(int title)Android 系统可能仍然调用默认MyAlertDialogFragment()构造函数,然后不传递参数。Fragment

于 2012-12-23T14:45:03.030 回答
4

因为当android重新创建一个fragment时,它总是使用空的构造函数,并且通过使用newInstance()你可以设置fragment在重新创建时使用的数据,例如当屏幕旋转时

例如:

   public static FragmentExample newInstance(Parcelable uri) {
    FragmentExample fragmentExample = new FragmentExample();

    Bundle bundle = new Bundle();
    bundle.putParcelable("Uri", uri);
    fragmentExample.setArguments(bundle);

    return fragmentExample;
}
于 2012-12-23T14:44:54.963 回答