[最全]Android安卓架构MVC、MVP、MVVM之间的区别和联系(图解+案例+源码)

一、问题背景

博主最近在准备春招面试中介绍自己简历中Android项目的MVP架构,但是博主发现若自身不彻底弄懂Android安卓架构MVC、MVP、MVVM之间的区别和联系,博主将无法准确地向面试官讲解自己Android项目的MVP架构,因此博主浏览了相关文章,做出了以下总结。

二、Android安卓架构MVC、MVP、MVVM

1.MVC(Model View Controller)

MVC各字母的全称及含义:

  1. Model:代表我们的数据模型,管理数据状态,比如Android项目中Java Bean。
  2. View:视图,即呈现给用户的UI,比如Android项目中的layout.xml文件、Activity和Fragment。
  3. Controller:控制者,负责处理用户与app之间的交互,包含业务逻辑。所以Controller是Model与View的中介,比如Android项目中Activity和Fragment。

MVC,Model View Controller,是软件架构中最常见的一种框架。简单来说就是通过controller的控制去操作model层的数据,并且返回给view层展示,具体见下图:
在这里插入图片描述
当用户触发事件的时候,view层会发送指令到controller层,接着controller去通知model层更新数据,model层更新完数据以后直接显示在view层上,这就是MVC的工作原理。

1.1 MVC的优缺点

MVC缺点:

  1. View与Model之间还存在依赖关系,Controller很重很复杂。
    由上面的MVC架构图可知,view层和model层是相互可知的,这意味着两层之间存在耦合,耦合对于一个大型程序来说是非常致命的,因为这表示开发,测试,维护都需要花大量的精力。
  2. 在Android中Activity即是View又是Controller,所以会很复杂。
    xml作为view层,控制能力实在太弱了,你想去动态的改变一个页面的背景,或者动态的隐藏/显示一个按钮,这些都没办法在xml中做,只能把代码写在activity中,造成了activity既是controller层,又是view层的这样一个窘境。大家回想一下自己写的代码,如果是一个逻辑很复杂的页面,activity或者fragment是不是动辄上千行呢?这样不仅写起来麻烦,维护起来更是噩梦。

1.2 Android中的MVC

那具体到Android上是怎么样一个情况呢?

大家都知道一个Android工程有什么对吧,有java的class文件,有res文件夹,里面是各种资源,还有类似manifest文件等等。对于原生的Android项目来说,layout.xml里面的xml文件就对应于MVC的view层,里面都是一些view的布局代码,而各种java bean,还有一些类似repository类就对应于model层,至于controller层嘛,当然就是各种activity咯。大家可以试着套用我上面说的MVC的工作原理是理解。比如你的界面有一个按钮,按下这个按钮去网络上下载一个文件,这个按钮是view层的,是使用xml来写的,而那些和网络连接相关的代码写在其他类里,比如你可以写一个专门的networkHelper类,这个就是model层,那怎么连接这两层呢?是通过button.setOnClickListener()这个函数,这个函数就写在了activity中,对应于controller层。是不是很清晰。

大家想过这样会有什么问题吗?显然是有的,不然为什么会有MVP和MVVM的诞生呢,是吧。问题就在于xml作为view层,控制能力实在太弱了,你想去动态的改变一个页面的背景,或者动态的隐藏/显示一个按钮,这些都没办法在xml中做,只能把代码写在activity中,造成了activity既是controller层,又是view层的这样一个窘境。大家回想一下自己写的代码,如果是一个逻辑很复杂的页面,activity或者fragment是不是动辄上千行呢?这样不仅写起来麻烦,维护起来更是噩梦。(当然看过Android源码的同学其实会发现上千行的代码不算啥,一个RecyclerView.class的代码都快上万行了呢。。)

MVC还有一个重要的缺陷,大家看上面那幅图,view层和model层是相互可知的,这意味着两层之间存在耦合,耦合对于一个大型程序来说是非常致命的,因为这表示开发,测试,维护都需要花大量的精力。

正因为MVC有这样那样的缺点,所以才演化出了MVP和MVVM这两种框架。

2.MVP(Model View Presenter)

MVP各字母的全称及含义:

  1. Model:代表我们的数据模型,管理数据状态。
  2. View:视图,即呈现给用户的UI,并且负责与客户进行交互。比如我们的XML/Activity/Fragment。
  3. Presenter:主持者,Presenter通过View接收用户的输入,然后在Model的帮助下处理用户的数据并将结果传递回View。Presenter通过接口与View进行通信。接口在presenter类中定义,它传递所需的数据。Activity/Fragment 及其他View视图组件实现此接口获得他们想要的数据并呈现数据。

MVP作为MVC的演化,解决了MVC不少的缺点,对于Android来说,MVP的model层相对于MVC是一样的,而activity和fragment不再是controller层,而是纯粹的view层,所有关于用户事件的转发全部交由presenter层处理。下面还是让我们看图:
在这里插入图片描述
从图中就可以看出,最明显的差别就是view层和model层不再相互可知,完全的解耦,取而代之的presenter层充当了桥梁的作用,用于操作view层发出的事件传递到presenter层中,presenter层去操作model层,并且将数据返回给view层,整个过程中view层和model层完全没有联系。看到这里大家可能会问,虽然view层和model层解耦了,但是view层和presenter层不是耦合在一起了吗?其实不是的,对于view层和presenter层的通信,我们是可以通过接口实现的,具体的意思就是说我们的activity,fragment可以去实现定义好的接口,而在对应的presenter中通过接口调用方法。不仅如此,我们还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试。这就解决了MVC模式中测试,维护难的问题。

当然,其实最好的方式是使用fragment作为view层,而activity则是用于创建view层(fragment)和presenter层(presenter)的一个控制器。

2.1MVP的优缺点

优点:

  1. 将View与Model解耦,方便进行单元测试。
  2. Presenter层可通过实现接口与View层通信从而避免Presenter层与View层耦合。
  3. activity和fragment不再是controller层,而是纯粹的view层。

缺点:虽然是MVC模式的演变,但Presenter依旧很‘重’很复杂。

3.MVVM(Model View ViewModel)

MVVM各字母的全称及含义:

  1. Model:代表我们的数据模型,管理数据状态。
  2. View:视图,即呈现给用户的UI,并且负责与客户进行交互。比如我们的XML/Activity/Fragment。
  3. ViewModel:如上图所示,ViewModel与Presenter的区别,在MVVM中,View引用持有ViewModel,但ViewModel得不到任何关于View的信息。所以View与ViewModel之间存在着一对多的关系,一个View可以持有多个ViewModel。

在这里插入图片描述
从图中看出,它和MVP的区别貌似不大,只不过是presenter层换成了viewmodel层,还有一点就是view层和viewmodel层是相互绑定的关系,这意味着当你更新viewmodel层的数据的时候,view层会相应的变动ui。

三、Android安卓架构MVC、MVP、MVVM的源码实例

我们分别用MVC、MVP、MVVM设计模式来实现一个用户登入功能的界面,下方演示动图的主界面中有3个按钮,点击各个按钮将跳转到分别以MVC、MVP、MVVM架构实现的登录功能的界面,演示动图如下:
在这里插入图片描述
强烈建议您直接从该源码实例的Github网址中下载项目源码,并在Android Studio中浏览源代码并运行项目,这样即可详细地了解MVC、MVP、MVVM之间的区别与联系。

1.源码实例中的MVC架构

我们在Android Studio中可看到该源码实例项目的Android项目结构:
在这里插入图片描述
其中,该项目的MVC架构的View便是上图红框选中的activity_mvc_login.xml文件和include_login_view.xml文件;MVC架构的Controller便是MvcLoginActivity.java,而MVC架构的Model便是User.java

MVC架构中为Model的User.java的代码如下,我们可以看到User.java是一个典型的Java Bean:

package com.example.mvcmvpmvvm.mvc.Model;

public class User {
    private String userName;
    private String password;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

MVC架构中为Controller的MvcLoginActivity.java的代码如下:

package com.example.mvcmvpmvvm.mvc.controller;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.example.mvcmvpmvvm.R;
import com.example.mvcmvpmvvm.mvp.model.User;

/**
 * @author jere
 */
public class MvcLoginActivity extends AppCompatActivity {
    private EditText userNameEt;
    private EditText passwordEt;
    private User user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvc_login);

        user = new User();
        userNameEt = findViewById(R.id.user_name_et);
        passwordEt = findViewById(R.id.password_et);
        Button loginBtn = findViewById(R.id.login_btn);

        loginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                login(userNameEt.getText().toString(), passwordEt.getText().toString());
            }
        });
    }

    private void login(String userName, String password) {
        if (userName.equals("jere") && password.equals("123")) {
            user.setUserName(userName);
            user.setPassword(password);
            Toast.makeText(MvcLoginActivity.this,
                    userName + " Login Successful",
                    Toast.LENGTH_SHORT)
                    .show();
        } else {
            Toast.makeText(MvcLoginActivity.this,
                    "Login Failed",
                    Toast.LENGTH_SHORT)
                    .show();
        }
    }
}

由上述MvcLoginActivity.java的代码,我们可以看到MvcLoginActivity.java既是View又是Controller。
其符合MVC的缺点:

  1. View与Model之间还存在依赖关系,Controller很‘重’很复杂。
    由上面的MVC架构图可知,view层和model层是相互可知的,这意味着两层之间存在耦合,耦合对于一个大型程序来说是非常致命的,因为这表示开发,测试,维护都需要花大量的精力。
  2. 在Android中Activity即是View又是Controller,所以会很复杂。
    xml作为view层,控制能力实在太弱了,你想去动态的改变一个页面的背景,或者动态的隐藏/显示一个按钮,这些都没办法在xml中做,只能把代码写在activity中,造成了activity既是controller层,又是view层的这样一个窘境。大家回想一下自己写的代码,如果是一个逻辑很复杂的页面,activity或者fragment是不是动辄上千行呢?这样不仅写起来麻烦,维护起来更是噩梦。

2.源码实例中的MVP架构

在这里插入图片描述
Model层:

public interface IUserBiz {
    boolean login(String userName, String password);
}
package com.example.mvcmvpmvvm.mvp.model;

/**
 * @author jere
 */
public class User {
    private String userName;
    private String password;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
package com.example.mvcmvpmvvm.mvp.model;

/**
 * @author jere
 * 其中IUserBiz的Biz代表Business
 */
public class UserBiz implements IUserBiz {

    @Override
    public boolean login(String userName, String password) {

        if (userName.equals("jere") && password.equals("123")) {
            User user = new User();
            user.setUserName(userName);
            user.setPassword(password);
            return true;
        }
        return false;
    }
}

Presenter层:

package com.example.mvcmvpmvvm.mvp.presenter;

import com.example.mvcmvpmvvm.mvp.model.User;
import com.example.mvcmvpmvvm.mvp.model.UserBiz;
import com.example.mvcmvpmvvm.mvp.view.IMvpLoginView;

/**
 * @author jere
 */
public class LoginPresenter{
    private UserBiz userBiz;
    private IMvpLoginView iMvpLoginView;

    public LoginPresenter(IMvpLoginView iMvpLoginView) {
        this.iMvpLoginView = iMvpLoginView;
        this.userBiz = new UserBiz();
    }

    public void login() {
        String userName = iMvpLoginView.getUserName();
        String password = iMvpLoginView.getPassword();
        boolean isLoginSuccessful = userBiz.login(userName, password);
        iMvpLoginView.onLoginResult(isLoginSuccessful);
    }

}

View层:


public interface IMvpLoginView {
    String getUserName();
 
    String getPassword();
 
    void onLoginResult(Boolean isLoginSuccess);
}
package com.example.mvcmvpmvvm.mvp.view;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.example.mvcmvpmvvm.R;
import com.example.mvcmvpmvvm.mvp.presenter.LoginPresenter;

/**
 * @author jere
 */
public class MvpLoginActivity extends AppCompatActivity implements IMvpLoginView{
    private EditText userNameEt;
    private EditText passwordEt;
    private LoginPresenter loginPresenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvp_login);

        userNameEt = findViewById(R.id.user_name_et);
        passwordEt = findViewById(R.id.password_et);
        Button loginBtn = findViewById(R.id.login_btn);

        loginPresenter = new LoginPresenter(this);
        loginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                loginPresenter.login();
            }
        });
    }

    @Override
    public String getUserName() {
        return userNameEt.getText().toString();
    }

    @Override
    public String getPassword() {
        return passwordEt.getText().toString();
    }

    @Override
    public void onLoginResult(Boolean isLoginSuccess) {
        if (isLoginSuccess) {
            Toast.makeText(MvpLoginActivity.this,
                    getUserName() + " Login Successful",
                    Toast.LENGTH_SHORT)
                    .show();
        } else {
            Toast.makeText(MvpLoginActivity.this,
                    "Login Failed",
                    Toast.LENGTH_SHORT).show();
        }
    }
}

3.源码实例中的MVVM架构

在这里插入图片描述
ViewModel层:

public class LoginViewModel extends ViewModel {
    private User user;
    private MutableLiveData<Boolean> isLoginSuccessfulLD;
 
    public LoginViewModel() {
        this.isLoginSuccessfulLD = new MutableLiveData<>();
        user = new User();
    }
 
    public MutableLiveData<Boolean> getIsLoginSuccessfulLD() {
        return isLoginSuccessfulLD;
    }
 
    public void setIsLoginSuccessfulLD(boolean isLoginSuccessful) {
        isLoginSuccessfulLD.postValue(isLoginSuccessful);
    }
 
    public void login(String userName, String password) {
        if (userName.equals("jere") && password.equals("123")) {
            user.setUserName(userName);
            user.setPassword(password);
            setIsLoginSuccessfulLD(true);
        } else {
            setIsLoginSuccessfulLD(false);
        }
    }
 
    public String getUserName() {
        return user.getUserName();
    }
}

View层:

public class MvvmLoginActivity extends AppCompatActivity {
    private LoginViewModel loginVM;
    private EditText userNameEt;
    private EditText passwordEt;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvvm_login);
 
        userNameEt = findViewById(R.id.user_name_et);
        passwordEt = findViewById(R.id.password_et);
        Button loginBtn = findViewById(R.id.login_btn);
        loginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                loginVM.login(userNameEt.getText().toString(), passwordEt.getText().toString());
            }
        });
 
        loginVM = ViewModelProviders.of(this).get(LoginViewModel.class);
        loginVM.getIsLoginSuccessfulLD().observe(this, loginObserver);
    }
 
    private Observer<Boolean> loginObserver = new Observer<Boolean>() {
        @Override
        public void onChanged(@Nullable Boolean isLoginSuccessFul) {
            if (isLoginSuccessFul) {
                Toast.makeText(MvvmLoginActivity.this,
                        loginVM.getUserName() + " Login Successful",
                        Toast.LENGTH_SHORT)
                        .show();
            } else {
                Toast.makeText(MvvmLoginActivity.this,
                        "Login Failed",
                        Toast.LENGTH_SHORT)
                        .show();
            }
        }
    };
}

本文参考文献:
[1]教你认清MVC,MVP和MVVM三者的区别
[2]MVC、MVP、MVVM,我到底该怎么选?
[3]Android MVC MVP MVVM简单例子
[4]android 架构设计之MVC MVP MVVM
[5]Android框架MVC、MVP和MVVM探究(图解+案例+附源码)

  • 24
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
### 回答1: MVCMVPMVVM 都是软件架构模式,用于组织代码和实现分离关注点的目的。 MVC(Model-View-Controller)是最早的一种架构模式,它将应用程序分为三个部分:模型(Model)、视图(View)和控制器(Controller)。其中,模型表示应用程序的数据和业务逻辑,视图表示用户界面,控制器负责协调模型和视图之间的交互。 MVP(Model-View-Presenter)是在 MVC 模式的基础上发展而来的,它将控制器改为了 Presenter,Presenter 负责协调模型和视图之间的交互,同时也负责处理用户输入和业务逻辑。MVP 模式将视图和模型完全分离,使得视图可以独立于模型进行测试和开发。 MVVM(Model-View-ViewModel)是在 MVP 模式的基础上发展而来的,它将 Presenter 改为了 ViewModel,ViewModel 负责协调模型和视图之间的交互,同时也负责处理用户输入和业务逻辑。MVVM 模式引入了数据绑定机制,使得视图可以自动更新,同时也使得开发者可以更加专注于业务逻辑的实现。 总的来说,MVCMVPMVVM 都是用于实现分离关注点的目的,它们的区别在于各自的架构模式和角色的不同。MVC 模式是最早的一种架构模式,MVP 模式是在 MVC 模式的基础上发展而来的,MVVM 模式是在 MVP 模式的基础上发展而来的,引入了数据绑定机制。 ### 回答2: MVCMVPMVVM 都是一种设计模式,用于解决应用程序中视图、模型和控制器之间的关系问题。虽然它们都是为了实现分层架构而生,但它们在设计理念上有所不同,各有优劣。下面将分别介绍其区别联系MVC(Model-View-Controller)模式最早于 1970 年代提出,它将应用程序划分为三个主要部分:数据模型、视图(用户界面)和控制器。其中,数据模型表示应用程序中的数据,视图表示呈现数据的用户界面,控制器负责处理用户的输入,并更新数据模型和视图。MVC 的最大优点是能够有效地将应用程序分离为多个独立的组成部分,分层清晰,便于维护和修改。但缺点是随着应用程序功能的增加,控制器变得越来越复杂,难以维护。 MVP(Model-View-Presenter)模式是在 MVC 模式的基础上提出的,它将一个控制器改为了一个或多个 Presenter。在 MVP 模式中,Presenter 接收视图的用户输入,并将业务逻辑分离到另一个模块中进行进一步处理。这样做的好处是,可以将业务逻辑从视图中解耦出来,视图与模型之间的关系更加松散,Presenter 则作为中间件来进行调控。MVP 模式的主要优点是:视图和控制器之间的耦合度降低,Presenter 可以方便地进行单元测试,MVP 更加适合复杂的业务逻辑场景。 MVVM(Model-View-ViewModel)是一种新型的设计模式,它于 2005 年提出。MVVM 将控制器和 Presenter 都替换为 ViewModel, ViewModel 作为视图和模型之间的中间层,用于绑定和管理视图和模型的数据。MVVM 模式的最大优点是,能够通过数据绑定自动处理模型和视图之间的同步,视图可以实现高度的灵活性,而模型又可独立于视图进行单元测试和开发。但与此同时,MVVM 模式也有一些缺点,例如较高的维护成本,增加了框架学习的难度等。 总的来说,MVCMVPMVVM 都是为了更好地分离视图和模型之间的关系,实现高内聚低耦合的目标。而MVVM 又是在 MVCMVP 的基础上不断演化而来,它的优缺点各不相同,应该根据实际情况来进行选择和使用。 ### 回答3: MVCMVPMVVM 是三种常见的前端架构设计模式,它们都致力于将应用程序的构建分离成三个不同的组成部分,以此来改进代码的可维护性、测试性和可扩展性。 MVC 是 Model-View-Controller 的缩写,它的核心思想是将应用程序分成三个独立的部分。Model 负责处理应用程序中的数据,View 是用户看到的 UI 部分,Controller 负责协调 View 和 Model 之间的通信。 MVP 是 Model-View-Presenter 的缩写,它是从 MVC 演变而来的一种模式。MVP 强调了对 View 和 Model 的分离,Presenter 代替了 Controller的职责,它是 View 和 Model 之间的中介者,将 View 的事件转换为 Model 的数据操作。 MVVM 是 Model-View-ViewModel 的缩写,它是一种完全基于数据绑定的设计模式。在 MVVM 中,ViewModel 从 Model 中获取数据并将数据绑定到 View 中。当 ViewModel 中的数据发生变化时,View 会自动更新。 三种架构联系区别在于: 共同点: 1. 都将应用程序分成了不同的部分,有助于提高代码可维护性和可测试性等。 2. 都是基于分层架构的设计思想。 3. 都有一个中介者来处理数据和视图之间的通信。 区别: 1. MVC将数据直接放到View中,而MVPMVVM都在Presenter或ViewModel中进行逻辑处理。 2. MVPMVVM更加注重解决应用程序中的业务逻辑问题,而MVC则更加注重解决应用程序中的客户端问题。 3. MVVM是一种使用数据绑定和命令处理的模式,可以让开发人员更加关注数据和逻辑处理,而不用关注UI的布局和样式。 4. MVPMVVM都优化了MVC中的Controller,使得Presenter或ViewModel分离了View和Model,并且降低了代码复杂度。 无论是MVCMVP还是MVVM,它们都有各自的优缺点,开发人员可以根据具体情况选择最适合的架构

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐李同学(李俊德-大连理工大学)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值