两难困境:何时使用Fragments与活动:

我知道Activities被设计为代表我的应用程序的单个屏幕,而Fragments被设计为可重用的UI布局,其中嵌入了逻辑。

直到不久前,我开发了一个应用程序,因为它说应该开发它们。我创建了一个Activity来表示我的应用程序的屏幕,并将Fragments用于ViewPagerGoogle Maps。我很少创建ListFragment或其他可以重复使用多次的UI。

最近我偶然发现了一个只包含2Activities的项目,一个是SettingsActivity,另一个是MainActivityMainActivity的布局填充了许多隐藏的全屏UI片段,并且只显示了一个。在Activity逻辑中,应用程序的不同屏幕之间有许多FragmentTransitions

我喜欢这种方法的是,因为应用程序使用ActionBar,它保持不变,不会随着屏幕切换动画而移动,这是Activity切换所发生的事情。这给那些屏幕转换带来了更流畅的感觉。

所以我想我要问的是分享你目前关于这个主题的开发方式,我知道乍一看这可能看起来像是一个基于意见的问题,但我把它看作是一个Android设计和架构问题……不是一个真正基于意见的问题。

更新(01.05.2014):广场Eric Burke演示之后,(我不得不说这是一个很棒的演示,为Android开发人员提供了很多有用的工具。我与Square没有任何关系)

http://www.infoq.com/presentations/Android-Design/

根据我过去几个月的个人经验,我发现构建应用程序的最佳方法是创建一组片段来代表应用程序中的,并将所有这些片段呈现在一个Activity中。所以基本上你的应用程序中的Activities数量与流的数量相同。这样,操作栏在所有流程的屏幕上保持不变,但在更改流程时重新创建,这很有意义。正如Eric Burke所说,我也意识到,尽可能少使用Activities的理念并不适用于所有情况,因为它在他所谓的“上帝”活动中造成混乱。

229495 次浏览

好吧,根据Google的讲座(也许<强>这里,我不记得了),您应该考虑尽可能使用Fragments,因为它使您的代码更易于维护和控制。

但是,我认为在某些情况下,它可能会变得过于复杂,因为托管片段的活动需要在它们之间导航/通信。

我认为你应该自己决定什么是最适合你的。将一个活动转换为一个片段通常并不难,反之亦然。

我创建了一个关于这个dillema<强>这里的帖子,如果你想进一步阅读。

我的哲学是这样的:

仅在绝对绝对需要的情况下创建活动。使用可用于提交一堆片段事务的后栈,我尝试在我的应用程序中创建尽可能少的活动。此外,各种片段之间的通信比在活动之间来回发送数据容易得多。

活动转换是昂贵的,对吧?至少我认为是这样——因为旧的活动必须被销毁/暂停/停止,被推到堆栈上,然后新的活动必须被创建/启动/恢复。

这只是我的哲学,因为碎片被引入。

专家会告诉你:“当我看到UI时,我将知道是使用Activity还是Fragment”。一开始这没有任何意义,但随着时间的推移,你实际上可以告诉你是否需要Fragment

我发现有一个很好的练习对我很有帮助。当我试图向女儿解释一些事情时,我突然想到了这一点。

也就是说,假设一个框代表一个屏幕。你能在这个框中加载另一个屏幕吗?如果你使用一个新框,你必须从第一个框中复制多个项目吗?如果答案是肯定的,那么你应该使用Fragments,因为根Activity可以保存所有重复的元素,以节省你创建它们的时间,你可以简单地替换盒子的一部分。

但是不要忘记,你总是需要一个盒子容器(Activity),否则你的零件会分散。所以一个盒子里面有零件。

注意不要误用盒子。Android用户体验专家建议(你可以在YouTube上找到他们)什么时候我们应该明确加载另一个Activity,而不是使用Fragment(就像我们处理有类别的导航抽屉时一样)。一旦你对Fragments感到满意,你就可以观看他们所有的视频。更重要的是,它们是强制性的材料。

你现在能看看你的UI并弄清楚你需要Activity还是Fragment吗?你有新的视角吗?我想你做到了。

不要忘记活动是应用程序的块/组件,可以通过Intent共享和启动!所以你应用程序中的每个活动应该只解决一种任务。如果你的应用程序中只有一个任务,那么我认为你只需要一个活动和许多片段,如果需要的话。当然你可以在未来的活动中重用片段来解决另一个任务。这种方法将任务清晰和逻辑分离。你不需要为不同的片段集维护一个具有不同意图过滤器参数的活动。你在开发过程的设计阶段根据需求定义任务。

这比你意识到的要多得多,你必须记住,启动的活动不会隐式销毁调用活动。当然,你可以设置它,让你的用户单击按钮进入一个页面,你启动该页面的活动并销毁当前页面。这会导致很多开销。我能给你的最好的指导是:

**只有当主活动和这个活动同时打开有意义时才开始一个新活动(想想多个窗口)。

拥有多个活动是有意义的一个很好的例子是Google Drive。主活动提供了一个文件资源管理器。当打开文件时,会启动一个新活动来查看该文件。您可以按下最近的应用程序按钮,这将允许您返回浏览器而无需关闭打开的文档,然后甚至可能打开与第一个文档并行的另一个文档。

我做了一件事:尽可能少地使用片段。不幸的是,这几乎是可能的。所以,我最终得到了很多片段和一些活动。我发现了一些缺点:

  • ActionBar&Menu:当2个片段有不同的标题、菜单时,
    将很难处理。例如:添加新片段时,您可以更改操作栏标题,但是当从backstack弹出它时,没有办法恢复旧标题。在这种情况下,您可能需要在每个片段中添加一个工具栏,但请相信我,这会花费您更多的时间。
  • 当我们需要startForResult时,活动有,但片段没有。
  • 默认没有过渡动画

我的解决方案是使用一个活动来包装里面的片段。所以我们有单独的操作栏、菜单、startActivityForResult、动画、…

为什么我更喜欢在所有情况下的活动片段。

  • 活动是昂贵的。在片段中,视图和属性状态是分开的——每当片段位于backstack时,它的视图将被销毁。所以你可以堆叠比活动更多的片段。

  • Backstack操作。使用FragmentManager,可以轻松清除所有Fragments,插入比Fragments和etcs更多的内容。但是对于活动来说,操纵这些东西将是一场噩梦。

  • 一个更可预测的生命周期。只要主机活动不被回收。后栈中的Fragments将不会被回收。所以可以使用FragmentManager::getFragments()来查找特定的片段(不鼓励)。

在我看来,这并不重要。要考虑的关键因素是

  1. 你多久重用一次UI的部分(例如菜单),
  2. 该应用程序也适用于平板电脑吗?

碎片的主要用途是构建多窗格活动,这使得它非常适合平板电脑/手机响应式应用程序。

我使用Fragments来获得更好的用户体验。例如,如果您有一个Button,并且您想在单击它时运行假设一个Web服务,我将一个片段附加到父活动中。

if (id == R.id.forecast) {
ForecastFragment forecastFragment = new ForecastFragment();FragmentManager fm = getSupportFragmentManager();FragmentTransaction ft = fm.beginTransaction();ft.replace(R.id.main_content, forecastFragment);ft.addToBackStack("backstack");forecastFragment.setArguments(b);ft.commit();}

这样,用户就不必在另一个活动中移动。

其次,我更喜欢碎片,因为你可以在旋转过程中轻松处理它们。

与活动相比,fragment的一大优势是,用于片段的代码可以用于不同的活动。因此,它在应用程序开发中提供了复用性的代码。

每个应用程序使用一个活动来为fragment提供基础使用fragment作为屏幕,与activites相比,fragments轻量级碎片可重复使用碎片是更适合的应用程序,支持手机和平板电脑

这取决于你真正想要构建什么。例如navigation drawer使用片段。选项卡也使用fragments。另一个很好的实现,就是你有listview的地方。当你旋转手机并单击一行时,活动显示在屏幕的剩余一半。就个人而言,我使用fragmentsfragment dialogs,因为它更专业。加上它们在旋转中更容易处理。

您可以自由使用其中一个。
基本上,你必须评估哪个是你的应用程序最好的。想想你将如何管理业务流程以及如何存储/管理数据偏好。

想想看,Fragments如何存储垃圾数据。当你实现片段时,你有一个活动根来填充片段。因此,如果你试图用太多的片段实现很多活动,你必须考虑应用程序的性能,因为你正在操纵(粗略地说)两个上下文生命周期,记住复杂性。

记住:我应该使用碎片吗?为什么不应该?

问候。

由于Jetpack单活动应用是首选架构。特别是对于导航架构组件很有用。

几乎总是使用碎片。如果你知道你正在构建的应用程序将保持非常小,使用碎片的额外努力可能不值得,因此可以忽略它们。对于较大的应用程序,引入的复杂性被碎片提供的灵活性所抵消,这使得在项目中使用它们更容易。有些人非常反对碎片及其生命周期带来的额外复杂性,所以他们从不在项目中使用它们。这种方法的一个问题是Android中有几个依赖碎片的API,例如ViewPager和Jetpack导航库。如果你需要在你的应用中使用这些选项,那么你必须使用碎片来获得它们的好处。

摘自:Kristin Marsicano。“Android编程:大书呆子牧场指南,第4版。”Apple Books。

一些错误的想法:

  • 始终在您的应用程序中放置活动并使用碎片处理不同的屏幕。
  • 直接在活动中编写UI代码。
  • 通过碎片处理屏幕之间的导航(我不是指选项卡,我的意思是例如全屏视图)。
  • 活动可以替换为碎片

事情是这样的!

碎片旨在实现UI的可重用部分,并在应用程序的任何需要的部分中使用它们。它们不是为了替代活动而设计的。

什么时候我们必须使用它们中的每一个?

  • 当我们有一个独立屏幕,其中有一些不同的UI部件(选项卡,可扩展屏幕,部分屏幕等)时,我们应该使用有一些碎片的活动在同一屏幕中单独实现和处理不同的UI部分。
  • 应用程序的每个独立部分实际上是一个组件,与其他部分的概念上不同相同,它需要有一个独立活动。例如,登录部分可能包含一些不同的场景,如使用用户名密码或使用指纹。每个场景都可以由一个片段实现,所有与登录相关的片段都应该由登录状态处理。但是例如,应用程序中订单的部分没有概念关系的登录,所以它必须有不同的活动,当然,它可能包含一些片段,如OrdersFrament、SubmitNewOrderFrament等,所有这些都必须由订单列表管理。
  • 不执行直接在活动中的UI。即使该活动中只有一个片段,也始终在片段中实现UI并将这些片段添加到活动中。它可以帮助您拥有更多可重用的代码并更轻松地更改UI。
  • 永远不要使用碎片来无限导航在应用程序中,即使你强制用户在返回堆栈中拥有有限数量的片段。事实是,当您将新片段添加到返回堆栈并将其删除时,它不会从内存中删除,除非父活动被销毁并且它只是不可见。因此,当您使用片段管理器返回堆栈时,通过在同一活动中的片段之间多次导航(尤其是在每次导航时创建一个新片段并将它们放入返回堆栈的情况下),您将在应用程序中获得错误码

我希望它能有所帮助。