【问题标题】:Android - How to avoid duplicate code between activitiesAndroid - 如何避免活动之间的重复代码
【发布时间】:2011-11-23 02:26:08
【问题描述】:

这是一个笼统的问题,但我会给你一个具体的例子。

我在一个应用中有很多活动。在所有活动中,都有一个 Facebook 按钮。当您单击该按钮时,它会将您带到特定的 Facebook 页面。我希望按钮在每个页面上的行为方式完全相同。

现在,在每个 Activity 中,我为 Facebook 按钮创建了一个 onClickListener(),并创建了意图并启动了 Activity。每个 Activity 中的代码都相同。

编写此代码一次并将其包含在多个活动中的最佳方法是什么?是否有包含其他 .java 文件?

我知道一个可行的解决方案是创建一个扩展 Activity 的基础 CustomActivity 类,然后让所有活动扩展 CustomActivity。然后将我的onClickListener() 代码放入CustomActivity。不过,我是 Java 新手,我不确定这是否是最好的方法。我的一些活动已经按原样扩展了其他自定义活动类,所以扩展扩展更多东西的东西可能会有点混乱,我不知道。

更新

在这里扮演魔鬼的拥护者:假设我选择了继承路线,并创建了一些我希望我的活动扩展的CustomActivityCustomActivity 将包含一堆我需要用于所有活动的通用代码,包括但不限于 Facebook 按钮功能。当我需要使用来自CustomActivity 的通用代码的 Activity 但该特定 Activity 中没有 Facebook 按钮时会发生什么?

【问题讨论】:

    标签: java android android-activity


    【解决方案1】:

    一个通用的基类可能是最好的方法。 (如果你的一些活动扩展了 Activity 并且一些扩展了 Activity 的子类(例如 ListActivity),它就不会那么好用了。

    另一种方法是创建一个单独的类来实现您的点击监听器的逻辑。这并没有消除所有重复的代码——每个活动仍然需要实例化和注册一个监听器——但是要做什么的逻辑只需要在监听器类中编写一次。

    在任一替代方案中,您都可以考虑将android:onClick 属性分配给按钮。这样你就不需要注册点击监听器了;您只需要在每个活动中实现目标方法。这对于基类方法特别有用。

    更新

    假设您采用继承路线,并且您想要一个没有 Facebook 按钮的活动。如果您正在使用android:onClick 技术,那么您不必在代码中做任何不同的事情——因为没有按钮会调用您的 onClick 方法,该方法只会坐在那里什么都不做。如果您在代码中安装 OnClickListener,那么您只需要在注册监听器之前测试按钮是否存在(即 findViewById() 没有返回 null)。

    【讨论】:

    • 有趣的方法。谢谢!
    【解决方案2】:

    一般来说,一个通用的基类并不是最好的方法(虽然它肯定是有效的)。

    这让我(以及我所知道的每一个“获得”OO 的 OO 程序员)真正摸索了一段时间,但您应该尽可能少地使用继承。每次这样做时,您都应该问自己是否真的没有其他方法可以做到这一点。

    找出答案的一种方法是对“is-a”测试非常严格——如果您将基本活动称为“Facebook 活动”,您真的可以说每个孩子都“是”一个 Facebook 活动吗?可能不是。此外,如果您决定将 Twitter 添加到某些页面(而不是其他页面),您如何做到这一点?

    并不是说继承完全没有了!一个很好的解决方案可能是扩展一个控件来启动您的 facebook 活动并将其称为 facebook 按钮——让它封装您连接到 facebook 所需的所有内容。现在您可以通过简单地将其拖到任何页面上来添加它(我很确定 android 工具可以让您将新组件添加到托盘)。它不像扩展您的活动课程那样“免费”,但从长远来看,它会减少您的压力。

    你现在可能不会相信我,我们都需要从自己的经验中学习,只要记住这一点,并随着时间的推移使用它来评估你的代码。

    --编辑、评论回复--

    您可以将任何您认为会经常使用的 facebook 活动封装在它自己的类中 - 将其降至最低限度,这样您就可以将其添加到单行中的任何类中。

    但是,在某些时候,您可能会认为它仍然是太多样板,我完全理解。那时你可以使用你建议的抽象基础活动,但我不会硬编码它来明确处理 facebook,而是让它支持诸如 facebook(也许还有其他)之类的行为,并打开这些行为随心所欲。然后,您可以告诉它不要将 Facebook 行为添加到给定屏幕(如果您愿意),或者在 Twitter 中添加其中一些。

    你可以使这个样板最小化,例如,如果你想要“标准”功能,你不应该做任何特别的事情,如果你想禁用 facebook,你可以用以下方式启动你的构造函数:

    super(DISABLE_FACEBOOK_BEHAVIOR);
    

    如果您想要一个也启用 Twitter 的工具,您可以使用:

    super(DISABLE_FACEBOOK_BEHAVIOR, ENABLE_TWITTER_BEHAVIOR);
    

    使用 AbstractAction(BehaviorEnum... 行为) 之类的构造函数。

    这更灵活,实际上,如果您的活动是问心无愧的“行为支持活动”,您实际上可以说每个活动。

    当然,这是一个非常好的方法,一开始不那么灵活,然后在需要时重构为这样的模式,只要注意你的继承模型会导致问题,这样你就不会在你修复它之前让它把你搞砸太久。

    【讨论】:

    • 你有一些优点。我最初担心继承的事情,因为当我在某些 Activity 中没有 Facebook 按钮但我仍然需要使用 FacebookActivity 类的其他方面时会发生什么...
    【解决方案3】:

    嗯,扩展事物是 OOP 的原则,所以我认为拥有多个级别的子类不是问题。您考虑的解​​决方案在我看来是最好的。

    【讨论】:

      【解决方案4】:

      当然。使用继承来获得一些可重用性,就像使用 OOP 一样。你会发现,随着你的进步,你想要在你的活动中重用的东西越来越多——这些东西比 FB 按钮的 onClickListener 更复杂——所以开始构建一个好主意不错的、可重复使用的“超级”活动,您可以从中继承。

      【讨论】: