Android上的MVC模式


497

是否可以在Android版Java中实现模型-视图-控制器模式?

还是已经通过活动实施了?还是有更好的方法来为Android实现MVC模式?


64
您的问题很好。但是我认为标记为解决方案的答案是不正确的。这可能会误导几个人。
萨格哈尔2014年

4
查看我的2篇文章,从这里开始Android架构:MV?
Dori 2015年

1
另外还有遵守MVC的其他规则集吗,还是因为Activity,XML和Resources而已经针对MVC量身定制了Android开发?
乌冬之焰

3
@Dori,我修复了您的链接:Android体系结构:MV?
Andreybeta

本文通过一个实际示例与您在android中寻找MVC完全匹配:digigene.com/architecture/android-architecture-part-2-mvc
Ali Nem,

Answers:


239

在Android中,您没有MVC,但是您具有以下条件:


3
@JDPekham,为什么要说“如果不谈论布局/视图就无法实例化活动”?实例化一个活动不需要与视图对话,实际上与视图对话绝不是Activity实例化的一部分。您可以(但不必)调用各种活动方法,这些方法在您认为合适时与您的视图进行交互。第二个问题:假设Activity是要扮演“控制器”角色的(我相信许多Android开发人员会这样看),为什么不从Activity谈您的观点呢?

8
对于任何说“ Android是MVC”的人,请尝试Backbone.js(是,客户端js)一周,然后再返回并说“ Android是MVC”。您最终将理解这个问题以及我们为什么继续问:)
Mark Peterson

14
“在Android中,您没有MVC” ???? 与其他语言一样,在Android中,如果需要MVC,则拥有MVC。
Lorenzo Barbagli

1
@LorenzoBarbagli他的意思是,Android不会按设计在应用程序中强制执行MVC(就像iOS一样)。如果要实现MVC所提供的功能,则必须自己实现MVC,MVP或其他功能,即关注点分离和易于测试的隔离模型。
Piovezan

否。Android中肯定有MVC,但更隐含了。根据Android如何构建所有内容,它只是以不同的方式实现。
6rchid

229

没有通用的MVC模式。MVC是一个概念,而不是坚实的编程框架。您可以在任何平台上实现自己的MVC。只要您坚持以下基本思想,就可以实现MVC:

  • 模型:渲染内容
  • 视图:如何渲染
  • 控制器:事件,用户输入

还要这样考虑:在对模型进行编程时,模型不必担心渲染(或平台特定的代码)。该模型将对视图说,我不在乎您的渲染是Android还是iOS还是Windows Phone,这就是我需要您渲染的内容。该视图将仅处理特定于平台的呈现代码。

当您使用Mono共享模型以开发跨平台应用程序时,这特别有用。


12
没错,这是理论,人们是实际的!
TWiStErRob

1
@TWiStErRob但是,设计模式是理论上的抽象概念,而不仅仅是实现它们的一种方法。对我来说,宣称“我不想从理论上理解MVC,我只是想实现它”听起来像是可能导致“我要在厨房里放一台洗衣机,因为洗衣机实现了Cleaner™模式”厨房需要这个。”
路加福音

1
我认为示例是无价的,因为它们表明了其他人的想法。可以改善他们并从他们的努力中学习。无需所有人重新发明轮子。在Android及其复杂的生命周期中,存在设计模式中未解决的问题,但每个人都会面对它们。这就是我的实际意思。
TWiStErRob

47

Android上的动作,视图和活动是使用Android UI 的固有方法,并且是模型-视图-视图模型(MVVM)模式的实现,并且是在结构上与Model-view类似(在同一家族中) –控制器。

据我所知,没有办法打破这种模式。可能可以做到,但是您可能会失去现有模型的所有好处,并且必须重写自己的UI层才能使其正常工作。


29

经过一番搜索,最合理的答案如下:

MVC已在Android中实现为:

  1. View =布局,资源和内置类,例如Buttonandroid.view.View
  2. 控制器=活动
  3. 模型=实现应用程序逻辑的类

(顺便说一下,这意味着活动中没有应用程序域逻辑。)

对于小型开发人员而言,最合理的做法是遵循这种模式,而不是尝试做Google决定不做的事情。

PS注意,Activity有时会重新启动,因此它没有放置模型数据的位置(导致重新启动的最简单方法是android:configChanges="keyboardHidden|orientation"从XML中忽略并打开设备)。

编辑

我们可能在谈论MVC,但是可以说FMVCFramework--Model--View--Controller。该框架(Android OS)强加了其组件生命周期和相关事件的概念,并且在实践中,控制器Activity/ Service/ BroadcastReceiver)首先负责处理这些框架施加的事件(例如onCreate())。用户输入是否应该单独处理?即使需要,也无法将其分开,用户输入事件也来自Android。

无论如何,将更少的非Android专用代码放入Activity/ Service/ BroadcastReceiver会更好。


3
活动具有直接访问UI的权限,而在MVC控制器中,该控件不应了解该视图(反之亦然)。
Konrad Morawski 2014年

2
@KonradMorawski嗯....一个查看了解有关显示的东西有关控制器?比如说Button了解控制器的孩子?Views只知道显示事物似乎更合乎逻辑。考虑到Model仅了解数据的性质,这就是为什么需要Controller的原因:必须同时了解ModelView
18446744073709551615

4
显然,View需要了解控制器,才能将事件委托给控制器。控制器将其跟进模型并告知View结果是什么(以便它可以显示出来)。控制器不会使视图膨胀(而Activity会膨胀),它也不应该了解有关按钮,文本框,列表等的信息(而Activity则知道)。
Konrad Morawski 2014年

1
我认为它Service也属于控制器的保护范围
CL22 2014年

1
听说过观察者吗?到目前为止,IV的最佳分离是1.控制器只有模型实例,2.模型没有控制器或视图的知识,但是视图可以注册为模型观察者(因此模型有点了解视图,但他不知道视图是谁,他无关紧要)-完成加载数据的模型后,他会通知所有观察者(通常为1)和3。视图只有模型实例可以从中提取数据。这样,所有MVC框架只有2个依赖项。我认为2是最小值,因此它应该是最佳布局。
Srneczek

18

您没有一个MVC模式可以服从。MVC只是或多或少地声明您不应该混合数据和视图,以使例如视图负责保存数据或正在处理数据的类直接影响视图。

但是,尽管如此,Android处理类和资源的方式有时甚至被迫遵循MVC模式。在我看来,更复杂的是有时负责视图的活动,但同时又充当控制者。

如果您在XML文件中定义视图和布局,请从res文件夹中加载资源,并且如果避免或多或少地在代码中混杂这些内容,那么您还是遵循MVC模式。


14

您可以在Android中实现MVC,但是“本地不支持”该MVC会花费一些精力。

也就是说,我个人倾向于将MVP作为Android开发的一种更简洁的架构模式。通过说MVP,我的意思是:

在此处输入图片说明

我还在这里发布了更详细的答案。

在尝试了在Android中实现MVC / MVP的各种方法之后,我想出了一个合理的架构模式,在这篇文章中对此进行了描述:Android中的MVP和MVC架构模式


14

我发现在Android上实现MVC的最佳资源是这篇文章

我为我的一个项目遵循了相同的设计,并且效果很好。我是Android的初学者,所以不能说这是最好的解决方案。

我进行了一个修改:我为应用程序类中的每个活动实例化了模型和控制器,以便在横向景观模式更改时不会重新创建它们。


8
万一文章被删除,获得摘要将非常有用。
pqsk

12

我同意JDPeckham的观点,并且我相信仅XML不足以实现应用程序的UI部分。

但是,如果将“活动”视为视图的一部分,则实现MVC非常简单。您可以覆盖Application(由Activity中的getApplication()返回),在这里您可以创建一个在应用程序生命周期内都可以生存的控制器。

(或者,您可以按照应用程序文档的建议使用单例模式)


12

Android上的 MVC 体系结构最好遵循任何MVP,而不是android中的MVC。但是仍然根据问题的答案这可以解决

在此处输入图片说明

说明和准则

     Controller -
        Activity can play the role.
        Use an application class to write the
        global methods and define, and avoid
        static variables in the controller label
    Model -
        Entity like - user, Product, and Customer class.
    View -
        XML layout files.
    ViewModel -
        Class with like CartItem and owner
        models with multiple class properties
    Service -
        DataService- All the tables which have logic
        to get the data to bind the models - UserTable,
        CustomerTable
        NetworkService - Service logic binds the
        logic with network call - Login Service
Helpers -
        StringHelper, ValidationHelper static
        methods for helping format and validation code.
SharedView - fragmets or shared views from the code
        can be separated here

AppConstant -
        Use the Values folder XML files
        for constant app level

注意1:

现在,这是您可以做的魔术。对代码进行分类后,编写一个基础接口类,例如IEntity和IService。声明常用方法。现在,创建抽象类BaseService并声明您自己的方法集并进行代码分离。

注意2:如果您的活动正在呈现多个模型,则与其在活动中编写代码/逻辑相比,不如将视图分成多个片段。那就更好了。因此,将来如果需要在视图中显示更多模型,请再添加一个片段。

注意3:代码分离非常重要。体系结构中的每个组件都应独立且没有逻辑。如果您碰巧有某种依赖逻辑,则在两者之间编写一个映射逻辑类。这将对您将来有所帮助。



9

Android的MVC模式是通过其Adapter类实现的。他们用“适配器”代替控制器。适配器说明如下:

Adapter对象充当AdapterView和该视图的基础数据之间的桥梁。

我只是针对从数据库读取数据的Android应用程序进行调查,所以我还不知道它的工作原理。但是,它看起来有点像Qt的Model-View-Delegate体系结构,他们声称该体系结构是从传统MVC模式发展而来的。至少在PC上,Qt的模式运行良好。


9

尽管这篇文章似乎过时了,但我想添加以下两个内容,以了解该领域针对Android的最新发展:

android- binding-提供一个使android view小部件绑定到数据模型的框架。它有助于在android应用程序中实现MVC或MVVM模式。

roboguice -RoboGuice消除了开发中的猜测。注入您的视图,资源,系统服务或任何其他对象,然后让RoboGuice处理细节。


9

模型视图控制器(MVC)

在此处输入图片说明


描述:

  • 当我们必须在软件开发中处理大型项目时,通常会使用MVC,因为它是组织项目的通用方法。
  • 新开发人员可以快速适应项目
  • 也帮助大型项目的开发和跨平台。

MVC模式本质上是这样的:

  • 型号:显示内容。这可以是数据源(例如:服务器,应用程序中的原始数据)
  • 查看:显示方式。这可以是xml。因此,它充当表示过滤器。视图被附加到其模型(或模型部分),并获取表示所需的数据。
  • 控制器:处理诸如用户输入之类的事件。这是活动

MVC的重要功能: 我们可以修改Model或View或Controller仍然不影响其他

  • 假设我们更改了视图的颜色,视图的大小或视图的位置。这样做不会影响模型或控制器
  • 假设我们更改了模型(而不是从服务器获取的数据而不是从资产获取的数据),仍然不会影响视图和控制器
  • 假设我们更改了Controller(活动中的逻辑),它将不会影响模型和视图

2
我只使用过控制器作为查看/模型中继信息的渠道。我很好奇您如何直接建立模型和视图。您是否有此实现的来源或示例?
杰克逊克

7

我认为最有用的简化说明在这里:http : //www.cs.otago.ac.nz/cosc346/labs/COSC346-lab2.2up.pdf

从我在这里看到和阅读的所有其他内容来看,实现所有这些东西会使它变得更加困难,并且与android的其他部分不太匹配。

通过活动实现其他侦听器已经是Android的标准方法。最无害的方法是像幻灯片中描述的那样添加Java Observer,并将onClick和其他类型的操作分组为仍在Activity中的功能。

Android的方式是Activity可以同时执行。对抗它并没有真正使扩展或将来编写代码变得更加容易。

我同意第二个职位。它已经实现了,而不是人们习惯的方式。无论是否在同一文件中,都已经存在分隔。无需创建额外的分隔符以使其适合其他语言和操作系统。


6
您提供的链接已损坏。
mmBs

6

令人惊讶的是,这里没有任何帖子回答了这个问题。它们要么太笼统,含糊,不正确,要么不解决android中的实现。

在MVC中,视图层仅知道如何显示用户界面(UI)。如果为此需要任何数据,它将从“ 模型”层获取数据。但是View不会直接要求模型找到数据,而是通过Controller来完成。因此,Controller  调用ModelView提供所需的数据。数据准备就绪后,控制器将通知View已准备好从模型中获取数据。现在,视图可以从模型获取数据。

该流程可以总结如下:

在此处输入图片说明

值得注意的是,View可以 通过Controller(也称为  被动MVC)或通过向模型注册可观察对象(即Active MVC)来观察模型中的数据,从而了解模型中数据的可用性  。

在实现部分,首先想到的一件事情是View应该使用哪个android组件?Activity  还是Fragment ?

答案是没有关系,两者都可以使用。该视图应该能够呈现设备和响应上的用户界面(UI),以用户与用户界面的交互。双方Activity  并Fragment  为此提供必要的方法。

在使用的示例应用程序这篇文章中我已经使用Activity 了视图层,但Fragment  也可以使用。

完整的示例应用程序可以在“MVC”分支找到我的GitHub库在这里

我还通过此处的示例介绍了Android中MVC架构的优缺点。

对于那些有兴趣,我已经开始了一系列的Android应用程序架构的文章在这里通过一个完整的工作程序中,我比较了不同的架构,即MVC,MVP,MVVM,为Android应用开发。


当教练指出,活动和片段,我应该采取的架构当然作为的看法,实际上应该是控制器和视图应该是独立的文件。您是否对此有任何意见或理由?
brandonx

我认为讲师对此并不准确。选择活动或片段作为控制器意味着将上下文传递给控制器​​。另一方面,视图也需要上下文以绘制到屏幕上。这种方式,即将上下文传递给控制器​​,使应用程序容易出现内存泄漏,我认为控制器不应携带状态。
阿里·尼姆

5

厌倦了Android上的MVx灾难,我最近制作了一个微型库,该库提供了单向数据流,类似于MVC的概念:https : //github.com/zserge/anvil

基本上,您有一个组件(活动,片段和视图组)。在内部定义视图层的结构和样式。您还定义了数据应如何绑定到视图。最后,您可以在同一位置绑定侦听器。

然后,一旦您的数据被更改-全局“ render()”方法将被调用,并且您的视图将使用最新数据进行智能更新。

这是一个组件的示例,其中的所有组件内部都具有代码紧凑性(当然,可以轻松分离Model和Controller)。这里的“ count”是一个模型,view()方法是一个视图,“ v-> count ++”是一个监听按钮单击并更新模型的控制器。

public MyView extends RenderableView {
  public MyView(Context c) {
      super(c);
  }

  private int count = 0;

  public void view() {
    frameLayout(() -> {              // Define your view hierarchy
      size(FILL, WRAP);
      button(() -> {
          textColor(Color.RED);      // Define view style
          text("Clicked " + count);  // Bind data
          onClick(v -> count++);     // Bind listeners
      });
    });
  }

使用分离的模型和控制器,它看起来像:

button(() -> {
   textColor(Color.RED);
   text("Clicked " + mModel.getClickCount());
   onClick(mController::onButtonClicked);
});

在每个按钮上,单击此数字将增加,然后将调用“ render()”,并且按钮文本将被更新。

如果您使用Kotlin,则语法会变得更加愉悦:http: //zserge.com/blog/anvil-kotlin.html。另外,没有lambda的Java还有其他语法。

该库本身非常轻巧,没有依赖项,不使用反射等。

(免责声明:我是这个图书馆的作者)


4

根据解释是,Xamarin团队解释(在iOS MVC“我知道这似乎不可思议,但等待一秒钟”):

  • 模型(数据或应用逻辑),
  • 视图(用户界面),以及
  • 控制器(后面的代码)。

我可以这样说:

Android上的模型只是可打包对象。视图是XML布局,而控制器是(活动及其片段)。

*这只是我的观点,并非来自任何资源或书籍。



3

我已经看到很多人说MVC已经在Android中实现,但这不是事实。Android默认不遵循MVC。

因为我不是Google会强加诸如iPhone之类的MVC实现的限制,但是它取决于开发人员在项目中想要的模式或技术,因此在小型或简单应用程序中,不需要使用MVC,但作为应用程序后来变得越来越复杂,需要对其代码进行修改,因此需要Android中的MVC模式。

它提供了修改代码的简便方法,还有助于减少问题。如果您想在Android上实现MVC,请按照以下给定的链接进行操作,并在您的项目中享受MVC的实现。

http://www.therealjoshua.com/2011/11/android-architecture-part-1-intro/

但是如今,我认为MVP与Android Architectural Pattern一起是开发人员开发干净和强大的android应用程序的最佳选择之一。


1
同意 Android具有足够的灵活性来吊死自己。您的活动可以处理MVC的所有三个方面,因此迅速变得庞大而复杂。
Scott Biggs 2014年

2

当我们将MVC,MVVMPresentation Model应用于Android应用程序时,我们真正想要的是拥有一个清晰的结构化项目,更重要的是,它更易于进行单元测试。

目前,如果没有第三方框架,您通常会有很多代码(例如addXXListener(),findViewById()等)不会增加任何业务价值。

而且,您必须运行Android单元测试,而不是普通的JUnit测试,这需要花一些时间才能运行,并使单元测试有些不切实际。基于这些原因,几年前,我们启动了一个开源项目RoboBinding-一个用于Android平台的数据绑定Presentation Model框架。

RoboBinding帮助您编写易于阅读,测试和维护的UI代码。RoboBinding消除了对诸如addXXListener之类的不必要代码的需求,并将UI逻辑转移到Presentation Model,这是一个POJO,可以通过常规JUnit测试进行测试。RoboBinding本身随附300多个JUnit测试以确保其质量。


1

以我的理解,Android处理MVC模式的方式如下:

您有一个活动,它充当控制器。您有一个负责获取数据的类-模型,然后有View类即视图。

在谈论视图时,大多数人只考虑XML中定义的视觉部分。别忘了View还具有一个程序部分,其中包含在Java类中定义的构造函数,方法等。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.