为什么使用newInstance for DialogFragment而不是构造函数?

时间:2012-12-23 14:35:41

标签: android constructor android-dialogfragment

查看DialogFragment的{​​{3}},可以看到静态newInstance方法来初始化新的警报对话框片段。我的问题是,为什么不使用构造函数来执行此操作,如下所示:

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

这不完全相同,还是以某种方式不同?什么是最好的方法和为什么

4 个答案:

答案 0 :(得分:22)

如果您创建一个通过构造函数接收对象的DialogFragment,那么当android 重新创建您的片段时,您将遇到问题。 这将是会发生的事情:

  1. 您的代码创建了一个对话框,调用您创建的构造函数并将一些参数作为依赖项传递。
  2. 您的对话框运行,并使用您通过构造函数
  3. 传递的依赖项
  4. 用户关闭应用
  5. 时间过去了,android杀死了片段以释放内存
  6. 用户再次打开应用
  7. android将使用默认构造函数重新创建对话框。没有参数会传递!
  8. 您的对话框将处于不受欢迎的状态。它可能会尝试使用您希望通过构造函数传递的实例变量,但由于它们不存在,您将获得空指针异常。
  9. 为避免这种情况,您不必依赖构造函数来建立依赖关系,而是在Bundles(参数和已保存的实例)中。这可能会迫使你在某些类中实现Parcelable,这很糟糕。

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

答案 1 :(得分:19)

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)为其提供的参数将为您保存并提供给(重新)创建的任何新实例。使用静态方法创建Fragment只是提供了一种简单的方法来设置所需的参数,同时保持零参数构造函数。

答案 2 :(得分:10)

如果使用MyAlertDialogFragment(int title)重载构造函数,如果需要重新创建MyAlertDialogFragment()并且不传递参数,则Android系统仍可能调用默认的Fragment构造函数。

答案 3 :(得分:2)

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

例如:

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

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

    return fragmentExample;
}