【问题标题】:Fragments seems to be overkill? No MVC architecture possible?碎片似乎是矫枉过正?不可能有 MVC 架构?
【发布时间】:2012-06-02 01:54:48
【问题描述】:

几天前我从片段开始,但对我来说似乎是有线的。我没有看到复杂性大幅增加的正当优势。 我不知道,我是否应该在我的 Activity 或 Fragment 中实现该功能。 首先,我尝试将其放入片段中,但这似乎通常是不可能的。

例如: 单击按钮后,我有一个对话框作为用户输入。 因此,我通过侦听器将按钮单击从片段转移到活动,并在活动中打开了对话框。在对话框中,我启动了新功能(因此在 Activity 中实现)。 Android 开发人员提示在片段中添加警报对话框:

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentAlertDialog.html

但是这个fragment还是被实现了,并且重加了activity(对话框的按钮动作在activity中)。

因此,模型和视图严重混淆。我没有在如此难以维护的静态代码中看到额外的价值?!

您对片段有什么看法和建议?

【问题讨论】:

  • 我没有足够的经验来回答,但我第一次通过片段让我质疑它们在非平板电脑应用程序中的用途。对于 UI 开发的适度改进,绝对会增加复杂性。

标签: android android-fragments design-patterns model-view-controller


【解决方案1】:

使用Fragments 时,您可以将它们视为View,将Activity 视为Controller。在我个人看来,Fragments 是 Google 对支持平板电脑的下意识反应,现在我们被它们困住了 :(

我每天都在使用碎片,我当然能感受到你的痛苦。当我第一次读到它们时,我心想,“这真的很酷”,但是在使用它们之后,它们在很多方面都不尽如人意,但主要是因为我会错误地使用它们:(

这是我遇到的一些陷阱......

  1. 不要在片段布局中使用onclick,因为处理点击的是Activity 而不是Fragment。如果您使用该属性,然后您在另一个Activity 中使用该片段,那么您必须记住将onclick 方法也添加到该Activity 中。因此,请使用findViewById,然后在片段的onCreateView 中手动附加点击处理程序。

  2. 与其他 Fragment 通信时,使用Activity 作为控制器来引导消息。 (很多关于如何使用接口的例子)。这里的关键是,如果您在一个设备上运行多个片段,其中一个片段将直接与另一个片段通信,那么您会遇到一些奇怪但可预测的行为。例如,如果 Fragment A 直接更新了 Fragment B 中的 View,但 Fragment B 不可见(因为您已经替换了它——考虑一个电话),那么当 Fragment B 可见时,View 可能不会更新,因为View 被重新创建。因此,如果您更新Fragment,请务必更新片段中的数据,然后更新onCreateView 中的View 部分,该部分在片段再次可见时调用(即,您已弹出当前片段,您现在显示的是前一个)

  3. 不要仅使用片段构建完整的应用程序。而是像往常一样构建应用程序,使用活动,然后将Fragment 视为具有美化视图(它就是)。即,设计应用程序,使您有多个片段和多个活动,并且某些活动可能使用超过 1 个片段。

我对 Fragments 的第一个想法是,我认为使用 Fragments 和一个 Activity 构建一个完整的应用程序会很棒......我最终完成了这个应用程序,但是使用这种方法我遇到了很多问题。我的下一个方法是使用多个片段和多个活动,并且效果更好。

底线是,如果您将 Fragments 用作 View,它们会很棒,但如果您开始尝试像活动一样使用它们,那么您将遇到问题 :( 想想 Activiy -> @ 987654342@ 作为 Controller -> View

我还建议您阅读和理解除了 Activity 生命周期之外的 Fragment Lifecycle(Pro Android 4 有一张很棒的图片来表示它),这样您就可以省去几个小时的痛苦:)

【讨论】:

  • 感谢您的建议。根据 1.:我在 Fragment 中实现了 onClickListeners。有时点击只会修改片段本身。除此之外,我通常在每个片段中实现一个公共侦听器接口,并在使用片段的活动中实现它。使用这种方法,我可以通过另一个侦听器将 onClicklistener 传输到活动起初这听起来很重载,但好处是,我可以使用视图 ID 来识别按钮单击,并且只在我的活动中使用不需要知道的侦听器我的片段中的 ui 元素。
  • 很好的描述和很好的建议。不知何故,我认为如果 Views 可以使用布局文件,并且如果自定义组件变得更容易和鼓励,那么我们就不需要 Fragments。我们可以有 Activity == Controller,View == View。但不知何故,Android 架构师很早就错过了这一点。作为另一个最佳实践,Fragment 应该处理点击、更改事件、触摸事件等。然后,Fragment 暴露出更像业务逻辑的侦听器:AuthenicateUser、ShareMovie 等。然后您的 Activity 与您选择用于显示的组件分离。
  • 我完全可以理解。几年后我才回到android并找到了碎片。我只是试图用他们和一个活动来构建一个完整的应用程序。对我来说幸运的是,我遇到了障碍。试图通过强制片段充当主机来制作视图寻呼机。问题太多,所以我转而在需要的地方使用活动和片段的组合。他们有自己的位置,但文档让它看起来就是你所需要的。
【解决方案2】:

片段提供视图逻辑,因此它们可以移植到其他活动。在大多数情况下,活动正在更多地成为真正的控制器的角色。在之前的 Android 架构中,视图逻辑和控制器逻辑混在一起,因为没有一个子类视图来实现他们的大部分应用程序。他们本质上是在 XML 布局文件中进行布局,然后直接在 Activity 中拉出 View 对象。所以这意味着 Activity 正在注册点击侦听器、按键侦听器、拖动逻辑等,这通常是您在其他工具包的另一个 View 子类中所做的。因为他们这样做了,这意味着您刚刚编写的非常酷的拖动多点触控手势 ListView 被卡在了那个 Activity 中。现在您想在另一个 Activity 中再次使用它。好吧,你是 S.O.L。使用 Fragments,您可以更轻松地将逻辑从 Activity 移动到 Fragment。现在从技术上讲,您可以将其移动到自定义组件视图中,但 Fragments 提供了另一个优势,即 Fragments 使您能够编写可以在平板电脑和较小设备上运行的应用程序,同时改变每个设备的布局。理解它是如何工作的很棘手,但是一个 Activity 可以包含多个 Fragment,每种形式的布局都有不同的布局。自定义组件几乎无法轻松完成的事情。加上自定义组件不能使用布局文件。您必须使用 Fragments 编写完整的 Java 代码。

我认为您提供的示例是一种快速而肮脏的设计片段的方法。您可以通过提取 Fragment 委托给的接口来轻松提取反向引用(this 的嵌套范围)。

【讨论】:

    【解决方案3】:

    好的,我用 mv 架构运行了它...

        public AlertDialog openLocInput() {
    
        AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
        alert.setTitle("Login");
        alert.setMessage("Enter Pin :");
    
        // Set an EditText view to get user input
        final EditText input = new EditText(getActivity());
        alert.setView(input);
    
        alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                jsonHandler.obtainMessage(1, input.getText().toString())
                        .sendToTarget();
                dialog.dismiss();
                return;
            }
        });
    
        alert.setNegativeButton("Cancel",
                new DialogInterface.OnClickListener() {
    
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        return;
                    }
                });
        return alert.create();
    }
    

    在 Fragment 中实现...从 Fragment 开始这个 alertdialog:

            fragment_userlocation_btn_addLocation.setOnClickListener(new OnClickListener() {
    
            public void onClick(View v) {
                openLocInput().setOwnerActivity(getActivity());
                openLocInput().show();
            }
        });
    

    也在 Fragments 中实现。

    但我仍然相信矫枉过正的理论......

    我认为

    我认为 Fragments 的真正优势在于平板电脑优化,但目前平板电脑的使用量与移动设备的使用量相比非常少。除此之外,平板电脑不如移动设备那么“移动”,并且不是上下文感知开发的重点......

    【讨论】:

    • 这就是复用。很难预测您何时会使用它,因为您无法预测未来的需求。就像生活中的很多事情一样,如果你忽视它太久,你手头的项目就会比你慢慢地做更小的改进要大得多。不要割草 10 年而不是每 2 周割一次。制定某种计划意味着您可以随着时间的推移进行一些小的更改来指导您的计划。
    猜你喜欢
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    相关资源
    最近更新 更多