ChatGPT解决这个技术问题 Extra ChatGPT

困境:何时使用片段与活动:

我知道 Activities 旨在表示我的应用程序的单个屏幕,而 Fragments 旨在成为可重复使用的 UI 布局,其中嵌入了逻辑。

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

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

我喜欢这种方法的地方在于,因为应用程序使用了 ActionBar,所以它保持原样,不会随着屏幕切换动画而移动,这正是 Activity 切换时发生的情况。这为这些屏幕过渡提供了更流畅的感觉。

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

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

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

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

查看我在 SO - stackoverflow.com/questions/24647078/… 的帖子
单一活动:原因、时间和方式(Android 开发者峰会 '18)youtube.com/watch?v=2k8x8V77CrU&feature=youtu.be
今天,这个问题的最佳答案是学习 SingleActivityArchitecture

K
Kaushik NP

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

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

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

但是不要忘记,您始终需要一个盒子容器 (Activity),否则您的零件将被分散。所以一个盒子里面有零件。

注意不要误用盒子。 Android UX 专家建议(您可以在 YouTube 上找到它们)我们何时应该显式加载另一个 Activity,而不是使用 Fragment(例如当我们处理具有类别的 Navigation Drawer 时)。一旦您对 Fragments 感到满意,您就可以观看他们的所有视频。更重要的是,它们是强制性材料。

您现在可以查看您的 UI 并确定您需要 Activity 还是 Fragment?你有没有新的视角?我想你做到了。


你有你提到的 youtube 提要的链接吗?我搜索“Android UX 专家”和“Android UX”,但不完全确定您在谈论哪些视频。
没有了,一年多前看的。搜索Android开发者官方谈论UX
考虑的一个例子:activity 有 parentActivity,所以我们可以在从通知进入时合成 backstack,但我认为没有这样的 parentFragment。
@ToolmakerSteve 是的,它是 getParentFragment,但这不是我的意思,伙计,请参阅 developer.android.com/guide/topics/manifest/…
P
Pang

我的哲学是这样的:

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

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

自从引入片段以来,这只是我的哲学。


是的,但正如您所写,有时需要使用活动。一个例子是相机屏幕,最好在横向模式下使用它。另一个示例是当您放置自定义 appWidget(在“桌面”——启动器应用程序上)时显示的配置屏幕。
感谢您的回答和分享您的经验所以您认为在 android 中将应用程序限制为一个 Activity 并在应用程序架构允许的情况下对所有屏幕使用 Fragment 是一种很好的做法?
那么如何解决片段需要互相传递“状态”的问题呢?所有片段中的所有状态都需要存在于一个活动中,否则您将被迫使用单例。
我不相信各种片段之间的通信比在活动之间来回发送数据要容易得多。
至少,onActivityResult() 比片段的回调更安全、更轻松。
C
Community

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

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

我认为你应该自己决定什么对你最好。将活动转换为片段通常并不难,反之亦然。

如果您想进一步阅读,我已经创建了一篇关于这个难题 here 的帖子。


感谢您的回答和分享您的经验所以您认为在 android 中将应用程序限制为一个 Activity 并在应用程序架构允许的情况下对所有屏幕使用 Fragment 是一种很好的做法?
这取决于项目,但如果它对您来说太复杂,您也可以分成多个活动。不要害怕使用任何方法。你也可以同时使用它们。也许有时使用片段而不是活动对您来说太难了。我认为你应该尝试使用碎片,但如果它妨碍你的方式太多,不要强迫它无处不在......
如果我想保持 ActionBar 的这种影响保持不变并且所有内容都被切换怎么办?是否有可能通过活动实现这一目标?
F
Francis

Jetpack 起,Single-Activity 应用程序 是首选架构。尤其适用于 Navigation Architecture Component

source


我今天第一次读到 Jetpack。 :) 自引入 Fragment 以来,我们构建了单活动应用程序。多活动要复杂得多。
@TheincredibleJan 你说得对,早在 Jetpack 之前,单活动应用程序架构就是更好的解决方案
C
Charuක

为什么在所有情况下我都更喜欢 Fragment 而不是 Activity。

活动很贵。在 Fragment 中,视图和属性状态是分开的——每当一个 Fragment 在 backstack 中时,它的视图就会被销毁。所以你可以堆叠比 Activity 更多的 Fragment。

后台操作。使用 FragmentManager,可以轻松清除所有 Fragment,插入更多 Fragment 等。但是对于 Activity 来说,操纵这些东西将是一场噩梦。

一个可预测的生命周期。只要宿主Activity没有被回收。 backstack 中的 Fragment 不会被回收。因此可以使用 FragmentManager::getFragments() 来查找特定的 Fragment(不鼓励)。


嗨,我阅读了您关于 Frag 优于 Act 的评论,您是否有任何项目可以在您的 Github Repo 中展示相同的内容?
C
Charuක

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

您多久会重复使用部分 UI(例如菜单),该应用程序是否也适用于平板电脑?

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


我会说片段的主要用途是制作自定义视图而不将它们视为自定义视图。反正就是这样。我们最初从 Google 展示的 Fragment 是一种制作平板电脑响应式应用程序的便捷方式,因此您可以根据需要将它们粘贴到不同的活动中。一种将代码或多或少附加到视图的方法,并将它们粘贴到您想要的位置(无需制作自定义视图)。
g
guest

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


在我们的应用程序中,活动的一种任务是拿着导航抽屉进入不同的片段。 :) 为什么我要处理片段的意图?为全局数据保存对“全局”数据类的静态引用并将一些值传递给片段的创建实例方法是清晰且合乎逻辑的。
T
TheHebrewHammer

这比您意识到的要多,您必须记住,启动的活动不会隐式破坏调用活动。当然,您可以设置它,以便您的用户单击按钮转到页面,启动该页面的活动并销毁当前活动。这会导致大量开销。我能给你的最好的指南是:

** 仅当主要活动和该活动同时打开有意义时才开始一个新活动(考虑多个窗口)。

Google Drive 就是一个很好的例子,说明何时进行多项活动是有意义的。主要活动提供了一个文件浏览器。打开文件时,会启动一个新活动来查看该文件。您可以按最近的应用程序按钮,这将允许您在不关闭打开的文档的情况下返回浏览器,然后甚至可能与第一个并行打开另一个文档。


重新“只有当主活动和这个活动同时打开有意义时才开始一个新活动(想想多个窗口)。”我不这么认为。使用 fragments attach/detach 方法可以很好地解决这种情况。
C
Charuක

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

ActionBar & Menu:当 2 个片段有不同的标题、菜单时,将很难处理。例如:添加新片段时,您可以更改操作栏标题,但是从后台弹出它时,无法恢复旧标题。对于这种情况,您可能需要在每个片段中都有一个工具栏,但相信我,这会花费您更多时间。

当我们需要 startForResult 时,activity 有但 fragment 没有。

默认没有过渡动画

我的解决方案是使用 Activity wrap 内部的片段。所以我们有单独的操作栏、菜单、startActivityForResult、动画……


非常有用的点,谢谢。你能澄清“包装片段的活动”吗?您是否为每个片段制作了单独的活动?如果是这样,你需要 Fragment 吗?
有一种方法可以恢复标题和内容。使用 getSupportFragmentManager().addOnBackStackChangedListener 添加侦听器。在该侦听器中获取当前片段,然后设置标题和内容。
V
Vadim Kotov

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


如何?你能提供一些例子吗?
@sofs1 你的问题没有多大意义。无论片段是从哪个活动中实例化的,片段中的任何代码都保持不变。
@TheincredibleJan 但是我们不能也说“无论从哪个活动实例化第二个活动,活动中的任何代码都保持不变。”?我看不出有什么区别。
C
Charuක

每个应用程序使用一个 Activity 为 fragment 使用 fragment 提供基础更适合同时支持手机和手机的应用药片


F
Franklin Hirata

您可以自由使用其中之一。基本上,您必须评估哪个是最适合您的应用的。考虑您将如何管理业务流程以及如何存储/管理数据首选项。

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

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

问候。


M
Massimiliano Kraus

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

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();
}

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

其次,我更喜欢 Fragments,因为您可以在轮换期间轻松处理它们。


是什么让该示例具有更好的用户体验?他们如何知道(或关心)他们正在做的活动或片段?
C
Charuක

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


h
hossam rakha

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

摘自:克里斯汀·马尔西卡诺。 “Android 编程:大书呆子牧场指南,第 4 版。”苹果图书。


M
Mansour

一些错误的想法:

始终在您的应用程序中放置一个活动,并使用片段处理不同的屏幕。

直接在活动中编写 UI 代码。

通过片段处理屏幕之间的导航(我不是指标签,我是指例如全屏视图)。

活动可以被片段替换。

事情就是这样!

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

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

当我们有一个独立的屏幕,其中有一些不同的 UI 部分(选项卡、可扩展屏幕、部分屏幕等)时,我们应该使用带有一些片段的活动来在同一屏幕中分别实现和处理不同的 UI 部分。

应用程序的每个独立部分实际上是一个在概念上与其他部分不同的组件,它需要有一个独立的活动。例如,登录部分可能包含一些不同的场景,例如使用用户名密码或使用指纹。每个场景都可以由一个片段来实现,所有与登录相关的片段都应该由 LoginActivity 处理。但是比如应用中的订单部分和login没有概念上的关系,所以它必须有不同的activity,当然也可能包含OrdersFragment、SubmitNewOrderFragment等所有必须的Fragment由 OrdersActivity 管理。

不要直接在活动中实现 UI。始终在片段中实现 UI 并将这些片段添加到活动中,即使该活动中只有一个片段。它可以帮助您拥有更多可重用的代码并更轻松地更改 UI。

即使您强制用户在后台堆栈中拥有有限数量的片段,也不要使用片段在应用程序中无限导航。事实是,当您将新片段添加到后台堆栈并删除它时,它不会从内存中删除,除非父活动被破坏并且它只是不可见。因此,当您使用片段管理器返回堆栈时,通过在同一活动中的片段之间多次导航(特别是在您在每个导航上创建一个新片段并将它们放入返回堆栈的情况下)您将在应用程序中获得 OutOfMemoryException .

我希望它会有所帮助。


自从 Jetpack Compose 发布以来,我认为没有理由再使用 Fragments 了。所有 UI 在设计上都是可重用的,单活动应用程序是最佳选择。只需通过 when 语句中的某些状态交换 UI,甚至可以将其包装在 AnimatedContent 中以添加过渡。