Fragments 作为静态内部类与独立公共类的设计逻辑是啥?

Posted

技术标签:

【中文标题】Fragments 作为静态内部类与独立公共类的设计逻辑是啥?【英文标题】:What is the design logic behind Fragments as static inner classes vs standalone public classes?Fragments 作为静态内部类与独立公共类的设计逻辑是什么? 【发布时间】:2014-04-07 02:24:33 【问题描述】:

我无法理解我刚刚开始的 android 软件设计的一个重要方面,据我所知,Fragment 设计已被采用以解耦代码,直觉是@987654324 @ 保持原样,Fragment 可以在其他地方重用,甚至可以在不同的活动中,或者可能与其他片段一起,在主/详细信息流或横向 UI 中。

好的,所以我在 SO 上看到了很多问题,询问为什么 Fragments 被放置为 Activity 中的静态内部类,答案是如果我们不将它们设为静态,@987654328 @ 可能包含对活动的引用,并且屏幕旋转或重新绘制之类的内容可能会泄漏活动或其他内容。

这让我回到第一点,我有一个问题,如果采用 Fragment 设计来解耦代码,那么我们为什么要将FragmentActivity 结合起来呢? 活动类中,而不是将它们作为独立的公共类?这不是和 Fragments 的存在完全矛盾吗?

这样的项目结构有什么缺点?每个Fragment 都是一个独立的类?鉴于我的 Fragment 代码可以增长到 1000 行,尤其是在尝试制作动画时,我认为这在除了预期的父 Activity 之外的其他 Activity 中更加整洁、解耦和可重用。

我们是否仍然受到上述内存泄漏问题的困扰? 我是否遗漏了一些关于设计逻辑的内容?请教育我。 有没有一种方法可以让 Fragments 作为内部类保留并在其他地方使用?我可能在这里也遗漏了一些东西......所以请通知我。

任何其他项目设计方法、概念、对我的直觉的修正都非常受欢迎,因为我刚刚从这里开始,我很想知道我的所有选择。

谢谢你:)

【问题讨论】:

能否请您添加一个链接,指向一个提倡 Fragments 作为活动的静态内部类的答案。这听起来像是一件荒谬的事情。我总是将 Fragments 与活动分离,并将它们放在自己的类和 .java 文件中,没有任何活动泄漏或其他此类废话。 @britzl,例如,当您在 Android Studio 中创建新活动时,默认情况下,片段(PlaceholderFragment)作为静态内部类嵌入到活动中,我必须手动将其取出从那里开始并将其放在自己的班级中。这是默认行为......这在我脑海中提出了问题。 也在 Fragments 的官方文档中。 developer.android.com/guide/components/fragments.html#Design“添加用户界面”下的“public static class ExampleFragment extends Fragment” 啊,我没有注意到官方文档中的“公共静态类”符号。无论如何,在我看来,片段应该被视为可重用的 UI 片段,无论是横向模式还是纵向模式,还是用于几个不同的活动。当然,有时一个片段只在一个活动中使用,但在这种情况下,我会质疑为什么它首先会被制作成一个片段。 @Akay 你是对的,来自谷歌的文档使用“活动中的公共静态类,在许多示例中”,而片段使用“片段事务”之类的术语在片段管理器中是荒谬的!我记得数据库“提交”和“回滚”表达式。真的,我不喜欢 android 架构,google 的架构师团队可能正在研究设计和模式,因为 android 对我来说是:许多代码行用于 LESS 结果!!! 【参考方案1】:

这让我回到第一点,我有一个问题,如果采用 Fragment 设计来解耦代码,那么我们为什么要通过将 Fragment 放在 Activity 类中来将其与 Activity 结合而不是将它们作为独立的公共课程?这不是和 Fragments 的存在完全矛盾吗?

片段的主要驱动力不是解耦,而是组合:可重用的用户界面片段可以在不同的配置中轻松组合在一起。从可组合性遵循模块化和从它解耦,所以是的,解耦是存在的,但它不是主要问题。

继续阅读fragment design philosophy。

模块化硬币还有另一面:如果两个事物属于一起,例如一个活动和一个仅与该活动一起使用的片段,它们最好保持在一起,而不是分散在整个代码库中,这样它们就更容易一起发展.像您的问题中的项目结构,其中活动和片段位于单独的包中,并不会真正遵循这一原则。

将片段保存在单独的类中但靠近相关活动的一种常见方法是使用命名前缀,以便它们在同一个包中按字母列表排序:例如FooActivity 与 FooDetailsFragment。

对于没有那么多代码且仅在一个活动中使用的简单片段,将它们作为该活动中的静态内部类非常好。

请尽量保持一致,以便其他阅读代码的人可以轻松地在代码库中找到自己的方式,并且 WTF/分钟代码指标保持在较低水平。

我们是否仍然受到上述内存泄漏问题的困扰?

不,泄漏仅适用于持有对外部类的引用的非静态内部类。包级类没有任何外部类可以引用。

由于片段共享托管活动的生命周期,因此泄漏外部对象并不是片段真正关心的问题。只是框架需要能够在没有任何外部类对象的情况下实例化片段,而static是对此的要求。

有没有一种方法可以让 Fragments 作为内部类保留并在其他地方使用?我可能在这里也遗漏了一些东西......所以请告诉我。

您可以在代码中使用点符号 Outer.Inner 或使用反射(例如 XML 文件)引用 Outer$Inner 来引用公共内部类。

虽然这在技术上是可行的,但这样做意味着您依赖于类的内部结构,这是一种设计风格。我真的会在外部类代码本身中引用内部类。

【讨论】:

感谢您抽出时间回答我,我真的发现您如何分解我的问题的每个部分很有用。我问这个的一个明显原因是因为默认情况下 Android Studio 会创建我所有的 Fragments 和静态内部类......我不想在不知道自己在做什么的情况下超越默认设置。根据您的解释,我觉得 Android Studio 假设 Fragment 仅用于该特定 Activity。 “我真的会在外部类代码本身中引用内部类。”,我无法理解这部分答案,你的意思是什么? @Eddnav 如果您有OuterClass.InnerFragment,请仅在OuterClass 中使用InnerFragment。片段应该是模块化的;将它们放在其他类中会降低模块化。【参考方案2】:

我想更好地了解与您的想法相反的逻辑;我一直在他们自己的课程中制作 Fragments,我的应用程序在重定向期间运行得像一块石头。我确实使用接口与管理 Activity 对话,使用适配器来管理 Fragments,并执行基本计费以确保我不会在重新加载时启动多个后台线程。

所以我检查http://developer.android.com/guide/components/fragments.html 这总是值得重读,而且你知道,底部的示例正是您所建议的,我每天都在使用:独立类中的两个公共片段,它们附加到活动并被活动附加。

如果有人真的在暗示你说的话,我怀疑他们是在说“片段必须始终嵌入到活动中,并且片段的生命周期直接受到宿主活动生命周期的影响。”方式,字面意思;它们的意思是嵌入在运行时中。

gl hf!

【讨论】:

就像我在 cmets 中提到的,我的来源是 Android Studio 默认行为和官方文档的一部分。尽管我发现这个信息量很大,“我确实使用接口与管理 Activity 对话,使用适配器来管理 Fragments,并执行基本计费以确保我不会在重新加载时启动多个后台线程。”没有尝试过这样做。看看它是否能改善我的练习。 酷,是的,不要害怕上课;一般来说,能够做到这一点可以确保你正在玩的对象是良好的,并且正在做你认为的事情。考虑契约设计模式:在一个完美的世界中,每个对象只使用构造函数中的参数、静态对象和它创建的对象。片段很好地体现了这种理念,实现接口是保持界限的好方法,但这样做 + 类系统会阻止。

以上是关于Fragments 作为静态内部类与独立公共类的设计逻辑是啥?的主要内容,如果未能解决你的问题,请参考以下文章

java内部类与匿名内部类作用分别是啥?

非静态内部类与静态内部类

Java内部类

(转)Java静态内部类的实例化问题

内部类与静态内部类

内部类