为啥使用片段,以及何时使用片段而不是活动?

Posted

技术标签:

【中文标题】为啥使用片段,以及何时使用片段而不是活动?【英文标题】:Why fragments, and when to use fragments instead of activities?为什么使用片段,以及何时使用片段而不是活动? 【发布时间】:2012-05-15 17:36:36 【问题描述】:

android API 11+ 中,Google 发布了一个名为 Fragment 的新类。

在视频中,Google 建议尽可能(link1、link2)使用片段而不是活动,但他们没有解释具体原因。

片段的用途和它们的一些可能用途是什么(除了一些可以通过简单视图/布局轻松实现的 UI 示例)?

我的问题是关于片段的:

    使用片段的目的是什么? 与使用活动/视图/布局相比,使用片段有哪些优点和缺点?

额外问题:

    你能给片段一些真正有趣的用途吗? Google 没有在视频中提及的内容? 在 Fragment 和包含它们的 Activity 之间进行通信的最佳方式是什么? 使用片段时要记住的最重要的事情是什么?根据您的经验有什么提示和警告?

【问题讨论】:

Dilemma: when to use Fragments vs Activities:的可能重复 相关帖子 - What are the differences between activity and fragment & what is the difference between view and activity in android development? 一个活动可以被认为是一个独立的微服务,而一个片段可以被认为是一个可嵌入的依赖项 【参考方案1】:

#1 & #2 使用片段的目的是什么? 与使用片段相比,使用片段的优点和缺点 活动/视图/布局?

片段是 Android 用于创建可重用用户界面的解决方案。您可以使用活动和布局(例如使用包含)来实现一些相同的目的。然而;片段从 HoneyComb 和更高版本连接到 Android API。让我详细说明;

ActionBar。如果你想在上面导航你的应用程序,你很快就会看到ActionBar.TabListener 接口给你一个FragmentTransaction 作为onTabSelected 方法的输入参数。您可能会忽略这一点,并做一些其他的聪明的事情,但您将使用 API,而不是使用它。

FragmentManager 以一种非常聪明的方式为您处理«返回»。 Back 并不意味着回到上一个活动,就像常规活动一样。这意味着回到之前的片段状态。

您可以使用酷炫的ViewPagerFragmentPagerAdapter 来创建滑动界面。 FragmentPagerAdapter 代码比常规适配器干净得多,它控制各个片段的实例化。

如果您在尝试为手机和平板电脑创建应用程序时使用 Fragments,您的生活会轻松很多。由于这些片段与 Honeycomb+ API 紧密相关,因此您也希望在手机上使用它们以重用代码。这就是兼容性库派上用场的地方。

您甚至可以而且应该将片段用于仅适用于手机的应用程序。如果您考虑到便携性。我使用ActionBarSherlock 和兼容性库来创建“ICS 外观”应用程序,这些应用程序在 1.6 版中看起来都一样。你会得到最新的功能,比如ActionBar,带有标签、溢出、拆分操作栏、viewpager 等。

奖金 2

在 Fragment 之间进行通信的最佳方式是 Intent。当您按下片段中的某些内容时,您通常会调用 StartActivity() 并提供数据。意图会传递给您启动的活动的所有片段。

【讨论】:

首先,谢谢。我感谢那些提供信息丰富(但简短)答案的人,而不仅仅是给我一个手册的链接。无论如何,除了特殊课程的额外功能之外,你能想到使用片段的优点和缺点? 我认为你必须更直接地提问。上面我只是给出了四大优势。 好的,与自定义视图和活动相比,缺点是什么? 一个片段不应该直接与另一个片段对话——而是通过父活动。这样您就不会得到意大利面条式的代码,而是易于管理代码。 Re “在片段之间进行通信的最佳方式是意图” 嗯?我不这么认为。 Intents 用于 activity 之间的通信。 “片段之间”的交流方式是……不要。也就是说,不要直接在片段之间进行通信,而是片段应该在自定义接口中对其拥有的活动进行回调,从而决定要做什么。【参考方案2】:

不确定您指的是什么视频,但我怀疑他们是否说您应该使用片段而不是活动,因为它们不能直接互换。在开发指南中实际上有一个相当的detailed entry,请考虑阅读它以了解详细信息。

简而言之,片段存在于 Activity 中,每个 Activity 可以承载许多片段。与活动一样,它们具有特定的生命周期,与活动不同,它们不是***应用程序组件。片段的优点包括代码重用和模块化(例如,在许多活动中使用相同的列表视图),包括构建多窗格界面的能力(主要在平板电脑上有用)。主要缺点是(一些)增加了复杂性。您通常可以使用(自定义)视图以非标准且不太健壮的方式实现相同的目的。

【讨论】:

更新问题。它现在有指向谷歌视频的链接。另外,感谢您的解释,但我仍然需要澄清我的问题。 阅读开发指南条目,它有足够的细节。您不太可能在 SO 上得到关于“片段的酷用途”的答案 - 含糊不清,没有单一的答案。开发指南中明确回答了第 4 个问题--developer.android.com/guide/topics/fundamentals/… 据我所知,此方法创建了一个依赖项,即哪个活动可以包含哪个片段。另外,请回答主要问题(前两个)。 感谢android开发者坚持回答基本问题。 ATM 我在 Fragment 类中没有看到任何对我有用的东西,而不是使用 XML“包含”标签。我认为有价值的事情是能够指定一种布局,该布局会神奇地转变为所有分辨率下的最佳用户体验。据我所知,您仍然需要自己在代码中执行此操作。另一个潜在价值是将代码+资源捆绑到可重用应用程序中找不到的可重用组件中,但似乎又不存在。我想要一个非常好的理由。 我开始理解 Google 建议使用片段的方式,但我完全同意 @NikolayElenkov 的观点。对我来说,使用活动似乎仍然是最强大且不太复杂的方式.. 【参考方案3】:

Fragment 是应用程序用户界面或行为的一部分,可以放置在 Activity 中,从而实现更加模块化的 Activity 设计。如果我们说片段是一种子活动,那并没有错。

以下是关于片段的要点:

    片段有自己的布局和行为以及自己的生命周期回调。

    您可以在活动运行时在活动中添加或删除片段。

    您可以在一个 Activity 中组合多个片段以构建多窗格 UI。

    一个片段可以用于多个活动。

    片段生命周期与其宿主活动的生命周期密切相关。

    当activity暂停时,所有可用在activity中的fragment也会停止。

    片段可以实现没有用户界面组件的行为。

    在 API 版本 11 的 Android 3 (Honeycomb) 中向 Android API 添加了片段。

更多详情,请访问官方网站,Fragments

【讨论】:

1.正如您在#8 中提到的,它不必有布局。 6.你错过了“手段”后面的部分。无论如何,感谢您帮助其他人更清楚地说明这一点。我会给你+1。 关于#8,无布局片段(即“无头”片段)的一个可能示例是执行一项尽管有点短(例如短的 HTTP 请求)仍然是需要在配置更改中幸存下来,因此取决于它们之间保留的确切片段实例(通过在片段上使用 setRetainInstance(true) )。至于布局片段,setRetainInstance(true) 没有多大意义,因为它会阻止与其视图相关的资源在必要时被释放(即内存泄漏)。 注意:“#8”现在是“#7”。【参考方案4】:

这是我在片段中找到的重要信息:

过去,Android 应用中的每个屏幕都是作为单独的 Activity 实现的。这对在屏幕之间传递信息造成了挑战,因为 Android Intent 机制不允许在活动之间直接传递引用类型(即对象)。相反,必须对对象进行序列化或提供可全局访问的引用。

通过使每个屏幕成为单独的 Fragment,这种数据传递令人头疼 完全避免。片段总是存在于一个上下文中 给定的 Activity 并且始终可以访问该 Activity。通过存储 活动中感兴趣的信息,每个片段的片段 screen 可以简单地通过 Activity 访问对象引用。

来源:https://www.pluralsight.com/blog/software-development/android-fragments

【讨论】:

确实如此,但是有解决方案:当它不是一个巨大的对象时使用 Parcelable(并且有一个插件可以使它更容易),如果它是一个巨大的对象,你总是可以使用当您进入新活动(或销毁它时,取决于您的要求)时将设置为 null 的静态引用。 @androiddeveloper:“使用 Parcelable”符合我对“使用 Fragments 避免数据传递头痛”的定义。如果在一系列屏幕经过时需要保持复杂的共享状态,那么 Activity + Fragments 是一个很好的解决方案,恕我直言。 (虽然我放弃了 Fragment 回栈,并且自己管理了“回”的含义。)【参考方案5】:

Activity 是应用程序中带有工具栏的全屏组件,其他所有内容最好是 Fragment。 一个带有工具栏的全屏父 Activity 可以有多个窗格、可滚动页面、对话框等(所有片段),所有这些都可以从父 Activity 访问并通过父 Activity 进行通信。

例子:

活动 A、活动 B、活动 C:

所有活动都需要重复相同的代码,以显示基本 例如工具栏,或从父活动继承(成为 管理繁琐)。 要从一个活动转移到另一个活动,要么所有活动都在内存中(开销),要么需要销毁一个活动才能打开另一个活动。 Activity 之间的通信可以通过 Intent 完成。

活动 A,片段 1,片段 2,片段 3:

没有代码重复,所有屏幕都有来自该活动的工具栏等。 从一个片段移动到下一页的几种方法 - 查看寻呼机、多窗格等。 Activity 拥有最多的数据,因此需要最少的片段间通信。如果仍然需要,可以通过接口轻松完成。 片段无需全屏显示,设计时具有很大的灵活性。 如果不需要视图,片段不需要膨胀布局。 多个活动可以使用同一个片段。

【讨论】:

完美答案!【参考方案6】:

片段在某些情况下特别有用,例如我们希望在所有页面中保留导航抽屉。您可以使用任何您想要的片段来扩展框架布局,并且仍然可以访问导航抽屉。

如果您使用了活动,则必须将抽屉保留在所有活动中,这会产生冗余代码。这是片段的一种有趣用法。

我是 Android 新手,但仍然认为片段以这种方式很有帮助。

【讨论】:

是的。但是,我有时仍然对使用 Fragment 的正确方法感到困惑,这是因为 Fragment 和 Activity 的生命周期都很复杂。 @androiddeveloper 你是不是主要使用activity? @MichaelAlanHuff 在支持平板的时候,我觉得还是用 Fragments 比较好。此外,当支持方向更改和其他类似事件时,您可能需要使用 DialogFragment,因为它允许您恢复它们 @androiddeveloper,我也是这么想的。我没有经常使用 DialogFragments。为了帮助逻辑模块化,许多安卓开发人员开始使用自定义视图来保存逻辑。这是来自 Airbnb 的工程师vimeo.com/127799187 最近关于自定义视图的演讲 @MichaelAlanHuff 如果您认为当前屏幕可能是另一个屏幕的一部分,那么使用片段也很有用。【参考方案7】:

我知道这已经被讨论到死了,但我想补充几点:

Frags 可用于填充Menus 并可以自行处理MenuItem 点击。从而为您的活动提供更多调制选项。您可以在 Activity 不知道的情况下执行 ContextualActionBar 等操作,并且基本上可以将其与 Activity 处理的基本内容(导航/设置/关于)分离。

带有子 Frag 的父 Frag 可以为您提供更多选项来模块化组件。例如。您可以轻松地交换 Frags,将新的 Frags 放入寻呼机或删除它们,重新排列它们。所有这一切都无需您的 Activity 了解,只需专注于更高级别的内容。

【讨论】:

【参考方案8】:

Fragments 存在于 Activity 中并具有:

它自己的生命周期 自己的布局 自己的子片段等

将 Fragments 视为它所属的主要活动的子活动,它不能单独存在,并且可以一次又一次地调用/重用。希望这会有所帮助:)

【讨论】:

其实关于第二点(“自己的布局”),这个是可选的。片段根本不需要有视图。【参考方案9】:

片段存在于 Activity 中,而 Activity 自身存在。

【讨论】:

“自身”?也许“靠自己”?还是“自己”?【参考方案10】:

1.使用片段的目的?

回答:
    处理设备外形差异。 在应用屏幕之间传递信息。 用户界面组织。 高级 UI 隐喻。

【讨论】:

【参考方案11】:

如果您以前写过前端,那么请使用前端组件,例如(React、Vue 或 Angular)。想想 Activity 中的可重用组件之类的片段。

【讨论】:

【参考方案12】:

Fragment 可以被认为是 ui 元素复合树中的非根组件,而活动位于复合森林(ui 树)中的顶部。

关于何时使用Fragment 的经验法则是,当片段作为孩子时具有冲突的属性,例如,它可能是沉浸式的,或者可能一起使用不同的样式,或者有一些其他的架构/逻辑差异,不适合现有的树同构

关于何时更喜欢 Activity 而不是 Fragment 的经验法则是,当任务(或一组连贯的任务)完全独立且可重复使用并且可以完成一些繁重的工作并且不应该进一步增加负担以符合另一个任务时父子组合(违反 SRP,第二个责任是遵守组合)。例如,MediaCaptureActivity 捕获音频、视频、照片等,并允许编辑、去除噪音、对照片进行注释等。此活动/模块可能有子片段,这些片段执行更精细的工作并符合常见的显示主题。

【讨论】:

以上是关于为啥使用片段,以及何时使用片段而不是活动?的主要内容,如果未能解决你的问题,请参考以下文章

何时使用活动转换与动态片段的模式

如何在片段而不是活动中使用 setContentView

使用单个片段显示UI而不是活动是一种好习惯吗?

片段的视图模型而不是访问活动视图模型?

如何在片段类而不是活动类中使用底页?

如何让自定义视图观察包含片段的生命周期事件而不是活动?