一个Activity和其他所有Fragment

161

我在考虑将一个屏幕用Activity实现,而将其他所有屏幕通过Fragments管理。我的答案是不好,但我仍然想更清楚地了解这个想法。

这个想法的优缺点是什么?

注意:

请不要给我提供有关Fragment和Activity的链接。

编辑:

以下是有关Fragments和activity的内容:

优点:

  1. Fragment是作为子活动与activities一起使用的。
  2. Fragment不能替代activities。
  3. Fragment被设计用于可重用性(需要知道如何实现可重用性)。
  4. Fragment是编写支持平板电脑和手机的代码的最佳方式。

缺点:

  1. 我们需要实现接口来从fragments获取数据。
  2. 对于对话框,我们必须走很长的路才能显示它。

如果我们不考虑平板电脑,为什么应该使用Fragments?activity和fragment之间的启动时间差异是多少?


1
@AlexanderLucas 我的回答是否定的,因为这样做会使你的代码变得不够模块化,增加了复杂性。 - Vineet Shukla
我想说的是,片段比活动加载要快得多。我目前正在重构为一种活动方法。 - theblang
3
任何看到这条信息的人,我停止了重构,因为事情变得非常复杂,非常快。 - theblang
21
这是一个很好的问题,不应该被关闭。 - Jim In Texas
这是一个来自Google在Udacity上的短视频,与此问题相关。 - Basheer AL-MOMANI
显示剩余3条评论
8个回答

95
这取决于您创建的应用程序。我使用过两种方法创建了几个应用程序,并不能说哪种方法总是比另一种更好。我最近创建的应用程序中,我使用了单个Activity方法和Facebook样式的导航。在从导航列表中选择项目时,我会更新一个单独的Fragment容器来显示该部分。
话虽如此,只有一个Activity也引入了很多复杂性。假设您有一个编辑表单,并且对于某些项目,用户需要选择或创建,需要他们转到新屏幕。使用Activities我们只需使用startActivityForResult调用新屏幕,但是使用Fragments没有这样的事情,因此您最终将值存储在Activity上,并且主编辑片段将检查Activity以查看是否已选择数据并应向用户显示。
Aravind所说的关于被困在单个Activity类型中也是正确的,但并不真正具有限制性。您的活动将是FragmentActivity,只要您不需要MapView,就没有真正的限制。如果您确实想显示地图,那么可以做到,但是您需要修改Android兼容性库,使FragmentActivity扩展MapActivity或使用公开可用的android-support-v4-googlemaps
最终,我认识的大多数开发人员都采用了一个Activity路线,以简化其代码。在平板电脑上,从UI上看,您有时候被迫使用单个Activity来实现任何疯狂的交互,这是设计师想出来的:)

Google终于将MapFragment发布到兼容库中,因此您不再需要使用android-support-v4-googlemaps hack。在此处阅读有关更新的信息:Google Maps Android API v2

-- 编辑2 --

我刚读了这篇关于现代(2017年)状态下的片段的优秀文章,并记起了这篇旧回答。分享链接如下:Fragments: The Solution to All of Android's Problems


6
有一个settargetfragment方法,你可以像处理startforresult过程一样处理该活动。 - Lalith B
1
在我看来,Activity 只是因为它是旧系统而存在。Fragment 以前并不存在。除了形式上的差别外,Activity 能做的事情 Fragment 都能做。我甚至可以想象,在某个时候,Activity 被移除,一切都成为 Fragment。 - User
1
总结一下仅使用片段的缺点,实际上并没有什么。正如Lalith B所说,startActivityForResult有对应的方法,而地图也不是问题。除此之外,所有事情(保存状态等)都可以通过片段的生命周期方法来处理。 - User

85

我即将完成一个项目(开发了5个月),它有1个主活动和17个全屏碎片。这是我的第二个基于片段的项目(之前的项目开发了4个月)。

优点

  • 主活动只有700行代码,非常好地管理了碎片导航的顺序。
  • 每个碎片都很好地分离为自己的类,并且相对较小(~几百行ui内容)。
  • 管理人员可以说:“嘿,我们如何更改这些屏幕的顺序”,我可以很容易地做到,因为这些碎片彼此不依赖,它们通过活动进行通信。我不必深入挖掘单个活动来查找它们互相调用的位置。
  • 我的应用程序非常重视图形,作为一个屏幕一个活动,所有这些子活动在内存中会使应用程序一直运行出现内存不足的情况,因此我必须finish() 所有不可见的活动,并且为导航创建相同的控制逻辑,就像我使用片段一样。因此,最好使用片段。
  • 如果我们曾经做平板电脑应用程序,则将更轻松地重新设计东西,因为所有内容已经很好地分离。

缺点

  • 你必须学习如何使用片段。

1
不确定是否有太多的片段和仅在活动时才使用......任何生产问题,责任在你! :) - Shahar
1
@Dinash 不要让操作系统重新启动你的活动。自己处理方向变化。在这里阅读更多信息:https://dev59.com/oG025IYBdhLWcg3wl3K- - Tamas
1
@Tamas,你有多个片段屏幕(例如主从屏幕)吗?如果有,你是如何处理的? - theblang
7
@Tamas 这种方法严重反对安卓系统的设计。这样做会导致出现GOD类(大而全的类)。安卓系统是为与活动(activity)配合使用而设计的,例如:你没有一个好的方法来处理多个片段中的工具栏。你没有开始片段以获得结果,还有很多其他的不支持。这意味着你必须重新编写已经存在的整个逻辑。那么局部广播接收器(Local broadcast receivers)、服务(services)和其他安卓组件怎么办?为了启动一个服务,你必须执行以下操作:getActivity()!= null…这真的很丑陋。此外,如果你有很多碎片(fragment),它们之间的通信也非常奇怪。 - Teodor
11
700行!!!“nicely”???这是什么意思?课程是免费的。 - beplaya
显示剩余10条评论

16

首先,无论你做什么,都要确保使用模型、视图、展示器的模块化设计,不要高度依赖于Activity或Fragment。

Activity和Fragment到底提供了什么?

  1. 生命周期事件和返回栈
  2. 上下文和资源

因此,只能用它们来实现这些功能,并且不要让它们过于复杂化。我认为即使在Activity或Fragment中实例化TextView也是不好的做法。这就是为什么像public View findViewById (int id)这样的方法是PUBLIC的

现在问题变得更简单了:我需要多个独立的生命周期事件和返回栈吗?如果你认为可能需要,那就使用Fragment。如果你认为永远不需要,那就不要使用Fragment。

最后,你可以自己创建返回栈和生命周期,但是为什么要重复造轮子呢?


嗯...实例化视图是不良实践和findViewById()公共之间的联系不清楚。虽然我同意关于视图实例化的观点,但我也认为从其他类(例如托管片段的活动在片段上调用它)调用findViewById是一种不良实践。我真的不知道为什么这是公共的,因为至少在我能想到的情况下,这会导致混乱的代码和非模块化设计。 - User
在我看来:如果你将一个活动传递到你的视图和Presenter中(将这两个组合称为“模块”),则可以在其他活动中重复使用该模块。如果有帮助的话,最好将活动作为仅公开必要内容的接口进行传递。如果你讨厌在活动之外查找视图,那么你可以通过该接口将所有视图注入到Pres./View中。 主要观点是,我认为Android编码应该在Actvities和Frags的概念之外完成,以便在两者之间轻松切换。然后,最好的选择变得清晰明了,你不会被困在代码的网络中只能使用其中之一。 - beplaya
3
放弃MVP模式,在安卓方面您会变得更好。您可以花费大量时间尝试将某个形状的积木塞进一个不同形状的洞中,这确实是一项挑战,但可能有更明智的方式花费时间来满足功能需求。 - straya

12

优点

由于所有片段彼此独立,因此可以从单个活动中控制您的片段。 片段具有自己的生命周期(onPauseonCreateonStart ...)。 通过拥有生命周期,片段可以独立响应事件,通过onSaveInstanceState保存其状态,并在需要时被恢复(例如,在接收到电话或用户单击返回按钮后恢复)。

缺点

  1. 增加了活动代码的复杂性。
  2. 您必须管理片段的顺序。

尽管如此,如果您需要创建一个应用程序,在其中要显示多个视图,则这是一个不错的想法。通过这种思路,您将能够在单个视图中查看多个片段。


2

这取决于您应用程序的设计布局。假设在设计布局中使用了ActionBar中的选项卡,那么在应用程序的单个活动中,可以通过单击选项卡来更改片段。因此,现在您拥有一个活动,假设在ActionBar中有三个选项卡,并且选项卡的视图由片段提供,这使得管理变得容易且可行。 因此,这完全取决于您的应用程序的设计方案以及您如何决定构建它。


1

优点:

  • 可以通过xml布局创建一个适用于多个屏幕尺寸和方向的单一界面。

缺点:

  • 需要在您的活动中编写更复杂的代码。

我认为这是一个好主意,因为根据当前屏幕大小和方向使用不同的xml布局可以使应用程序更易用,并减少发布多个版本的应用程序的需求,如果您计划发布适用于手机和平板电脑的应用程序。如果您的应用程序永远不会被手机和平板电脑同时使用,那么这可能不值得麻烦。


为了定位,不需要使用基于不同xml的布局。 - Vineet Shukla
@VineetShukla 是的,但这只是一个选项,就像根据屏幕尺寸使用不同的 XML 布局一样。例如,我的 Android 手机主屏幕在横向和纵向查看时有不同的布局。 - Ski

0
我支持将所有视图填充推迟到片段以提供更好的灵活性。例如,在平板电脑上有一个单独的着陆活动,聚合多个片段,并在手机上重用相同的片段以显示每个片段的一个屏幕。然而,在电话实现中,每个屏幕都会有一个单独的活动。这些活动不会有太多代码,因为它们会立即转移到它们的片段对应项进行视图填充。
我认为,当引入选项卡或侧滑菜单时,让电话实现改为单一的着陆活动是一个坏主意,因为选项卡或菜单导航只会导致完全新的屏幕。

我认为当引入选项卡或侧滑菜单时,手机应用程序的实现不必更改为单个着陆活动,因为选项卡或菜单导航只会导致完全新的屏幕,这是一个不好的想法。但是,在单个活动应用程序(平板电脑/手机)中,选项卡或侧滑菜单都不是问题。 - User

-1
我认为不使用单活动方法最重要的原因是可以利用活动生命周期。 活动包含应用程序某个部分的上下文行为,而片段则补充该行为。 有能力利用活动生命周期中可覆盖的步骤,例如 onPauseonResume 方法,有助于将一个活动的行为与另一个活动的行为分开。 此生命周期还允许您返回先前的上下文。 使用单个活动方法后,一旦您离开片段,就必须创建机制以返回到它。

4
我不相信这是真的。根据Fragment生命周期文档(http://developer.android.com/guide/components/fragments.html#Lifecycle):“包含该片段的活动的生命周期直接影响片段的生命周期,因此活动的每个生命周期回调都会导致每个片段执行类似的回调。例如,当活动收到onPause()回调时,活动中的每个片段也会收到onPause()回调。” - Ski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接