我已经看到了两个在应用程序中实例化新Fragment的一般做法:
Fragment newFragment = new MyFragment();
和
Fragment newFragment = MyFragment.newInstance();
第二个选项使用静态方法 newInstance()
,通常包含以下方法 .
public static Fragment newInstance()
{
MyFragment myFragment = new MyFragment();
return myFragment;
}
起初,我认为主要的好处是我可以重载newInstance()方法以在创建Fragment的新实例时提供灵活性 - 但我也可以通过为Fragment创建重载的构造函数来实现这一点 .
我错过了什么?
一种方法比另一种方法有什么好处?还是只是好习惯?
11 回答
实例化片段的最佳方法是使用默认 Fragment.instantiate 方法或创建工厂方法来实例化片段
注意:总是在fragment中创建一个空构造函数,而恢复片段内存会抛出运行时异常 .
我相信我有一个非常简单的解决方案 .
一些 kotlin 代码:
你可以得到这个论点:
在android中使用参数实例片段的最佳实践是在片段中使用静态工厂方法 .
您应该避免使用片段实例设置字段 . 因为每当android系统重新创建你的片段时,如果感觉系统需要更多的内存,那么它将通过使用没有参数的构造函数来重新创建你的片段 .
你可以在这里找到更多关于best practice to instantiate fragments with arguments的信息 .
关于最佳实践的问题,我想补充说,在使用一些REST Web服务时,使用混合方法创建片段通常是个好主意
对于显示用户片段的情况,我们无法传递复杂对象,例如某些用户模型
但我们可以做的是检查
onCreate
该用户!= null,如果没有 - 然后从数据层接收他,否则 - 使用现有的 .通过这种方式,我们既可以获得userId重新创建的功能,也可以获得Android的片段重新创建和用户操作的快捷性,以及通过保持对象本身或仅通过它的id来创建片段的能力
有点喜欢这个:
使用我看到的
newInstance()
的唯一好处如下:所以,我的看法是使用静态
newInstance()
实例化片段是一种很好的做法 .还有另一种方式:
我 disagree 与yydi answer说:
我认为这是一个解决方案而且是一个好的解决方案,这正是它由Java核心语言开发的原因 .
确实,Android系统可以破坏并重新创建你的
Fragment
. 所以你可以这样做:即使系统重新创建了
Fragment
,它也允许您从getArguments()
后拉someInt
. 这是比static
构造函数更优雅的解决方案 .对于我的意见
static
构造函数是无用的,不应该使用 . 如果将来你想扩展这个Fragment
并为构造函数添加更多功能,他们也会限制你 . 使用static
构造函数,您无法执行此操作 .Update:
Android添加了检查,标记所有非默认构造函数并显示错误 .
出于上述原因,我建议禁用它 .
如果Android决定稍后重新创建Fragment,它将调用片段的无参数构造函数 . 所以重载构造函数不是一个解决方案 .
话虽如此,将内容传递给Fragment以便在Android重新创建Fragment之后可用的方法是将包传递给
setArguments
方法 .因此,例如,如果我们想要将一个整数传递给片段,我们将使用类似的东西:
稍后在Fragment
onCreate()
中,您可以使用以下命令访问该整数:即使Fragment以某种方式由Android重新创建,也可以使用此Bundle .
另请注意:只能在将Fragment附加到Activity之前调用
setArguments
.Android开发人员参考中也记录了这种方法:https://developer.android.com/reference/android/app/Fragment.html
虽然@yydl给出了一个令人信服的理由,为什么
newInstance
方法更好:它仍然可以使用构造函数 . 要了解其原因,首先我们需要了解Android为何使用上述解决方法 .
片段之前可以使用,需要一个实例 . Android调用
YourFragment()
( no arguments 构造函数)来构造片段的实例 . 在这里,您编写的任何重载构造函数都将被忽略,因为Android无法知道要使用哪一个 .在Activity的生命周期中,片段如上所述创建并被Android多次销毁 . 这意味着如果将数据放入片段对象本身,则一旦片段被销毁,它就会丢失 .
要解决此问题,android会要求您使用
Bundle
(调用setArguments()
)存储数据,然后可以从YourFragment
访问它 . 参数bundle
受Android保护,因此保证为 persistent .设置此捆绑包的一种方法是使用静态
newInstance
方法:但是,构造函数:
可以做与
newInstance
方法完全相同的事情 .当然,这会失败,这也是Android希望您使用
newInstance
方法的原因之一:作为进一步的解释,这里是Android的片段类:
请注意,Android要求在构造时将参数设置为 only ,并保证这些参数将被保留 .
EDIT :正如@JHH的评论所指出的,如果你提供一个需要一些参数的自定义构造函数,那么Java将不会为你的片段提供一个no arg默认构造函数 . 因此,这需要您定义一个无参数构造函数,这是您可以使用
newInstance
工厂方法避免的代码 .EDIT :Android不再允许对片段使用重载构造函数 . 您必须使用
newInstance
方法 .setArguments()
没用 . 它只会带来一团糟 .