MVC、MVP以及MVP+VM

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chendeshan330/article/details/87811768

MVC模式

MVC模式的结构分为三部分,实体层Model,视图层View和控制层Controller。
在这里插入图片描述
工作原理:当用户触发事件,View层会发出指令到Controller层,由Controller层去通知Model层更新数据,Model层更新完数据后直接显示在View层上。
在Android工程中,View层对应xml布局文件,Controller层对应Activity,Model层对应各类Java bean和API等。

xml作为View层,控制能力太弱,比如动态改变TextView的字号、Progress的显示等,无法再xml中实现,只能在Activity中做,这就造成了Activity既是view层,又是Controller层,这样一来V和C就耦合在一起了,如果业务调整,可维护性与可测试性就降低了。

View和model可以直接交互,这就意味着两层之间存在耦合,当程序业务调整或代码量上升时,开发、测试、维护的难度都会上升。

MVP模式

在view和model之间新增presenter作为沟通的桥梁,presenter从model获取数据后,更新view的展示,使得view和model之间没有耦合,也将业务逻辑从view上抽离出来。

在这里插入图片描述
presenter处理业务逻辑并更新view,Activity只提供基础的操作view的能力,二者互相独立,view与业务分离。

当我们把业务逻辑抽取到presenter后,Activity基本上只剩下一些view的逻辑,真正实现了减负,变成了一个相对纯净的view。当我们需要修改view的逻辑时,就去找Activity,需要修改数据逻辑时,就去找Model,修改业务逻辑时就去找presenter,每个模块职责分明。

MVP+VM模式

通过DataBinding实现model到view的单向绑定,使用viewModel作为model和view 的适配层,减少view与model之间因频繁交互而产生的冗余代码。
在标签中引入data=User。当model变化时,通过data将数据映射到view上。当Button产生点击事件时交由presenter响应并处理。使用Databinding以后,开发流程上省略了findView,setView的过程,在写xml的时候就可以直接将model进行关联及映射。
在这里插入图片描述

如图:用户操作view,触发事件响应,通过presenter中转,传递给model进行数据处理,获取新数据后处理业务逻辑,并适配成不同状态的viewModel展示策略,view根据不同的viewModel进行更新。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="user"
            type="com.cardioray.testdatabinding.UserModel"/>

        <variable
            name="presenter"
            type="com.cardioray.testdatabinding.Presenter"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:orientation="vertical">

        <TextView
            android:layout_margin="10dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{user.firstName}"/>

        <TextView
            android:layout_margin="10dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{user.lastName}"/>

        <Button
            android:layout_margin="10dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            android:onClick="@{() -> presenter.onClickTest()}"/>

    </LinearLayout>

</layout>

View层的Model类

public class UserMoel extends BaseObservable {

    private String firstName;
    public ObservableField<String> lastName = new ObservableField<>();

    public UserModel(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName.set(lastName);
    }

    @Bindable
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        notifyPropertyChanged(com.cardioray.testdatabinding.BR.firstName);
}
}

MainPresenter不再与view频繁的交互,仅仅是作为view和model的连接器,主干逻辑更为清晰

public class MainPresenter implements IMainPresenter {

    private IMainView mIMainView;
    private UserModel mModel;

    public MainPresenter(IMainView iMainView) {
        mIMainView = iMainView;
    }

    // 请求数据
    @Override
    public void requestData() {
        mServerApi.getDepositInfo();
    }

    // 获取数据,通知view更新
    @Override
    public void onLoadDepositSuccess(UserModel model) {
        mModel = model;
        mIMainView.updateData(model);
    }

    // 接收并处理view的点击事件
    @Override
    public void onButtonClickAction(View v) {
        
    }
}

MainActivity中不再需要fingViewById,也不用定义Textview,Button的成员变量,全部交由DataBinding进行处理,相较MVP的实现,MainActivity进一步简化

public class MainActivity extends AppCompatActivity implements IMainView {
    private IMainPresenter mPresenter;
    private ActivityMainBinding mBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        mPresenter = new MainPresenter(this);
        mBinding.setPresenter(mPresenter);

        // 初始化页面数据
        mPresenter.requestData();
    }

    // 更新数据绑定
    @Override
    public void updateData(UserModel model) {
        mBinding.setData(model);
    }
    
    @Override
    public void showToast(String text) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
    }
}

总结

从mvc到mvpvm,项目中类虽然变多了,不过模块之间职责更加明确清晰。大部分情况,使用mvp结合databinding就可以较好的对view和model进行解耦,且代码冗余较少。
在MVC中发现Activity过重,所以引入MVP,Presenter作为View和Model的中转,达到解耦的目的。后来发现Activity提供view能力时冗余代码过多,所以引入viewModel(DataBinding),将xml与model进一步解耦,同时减轻model负担,不过此时并不算是mvvm,本质上在mvp的基础上,引入vm,因此presenter的中转作用还在,所以才演变成了现在的mvpvm。

没有更多推荐了,返回首页