Android开发中的MVC_MVP_MVVM

2019-11-26  本文已影响0人  发光的老金

为什么要学习MVC

需求(查询用户账号信息):

用户输入账号,点击按钮可进行查询账号信息,如果查询数据成功,则将数据展示在界面上;如果查询数据失败,则在界面上提示获取数据失败。

不实用框架实现需求

创建一个Activity,实现它的所有功能(获取用户输入信息,展示获取信息成功界面,展示获取信息失败界面,查询用户数据,业务逻辑)。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText edittext;
    private Button button;
    private TextView text;

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

    private void init() {
        edittext = findViewById(R.id.edittext);
        button = findViewById(R.id.button);
        button.setOnClickListener(this);
        text = findViewById(R.id.text);
    }

    @Override
    public void onClick(View v) {
        String userInput = getUserInput();
        getAccountData(userInput, new MCallBack() {
            @Override
            public void onSuccess(Account account) {
                showSuccessPage(account);
            }

            @Override
            public void onFail() {
                showFailPage();
            }
        });
    }

    //获取用户输入信息
    private String getUserInput() {
        return edittext.getText().toString().trim();
    }

    //展示获取信息成功界面
    private void showSuccessPage(Account account) {
        text.setText("用户账号:" + account.getName() + "|" + "用户等级:" + account.getLevel());
    }

    //展示获取信息失败界面
    private void showFailPage() {
        text.setText("获取数据失败");
    }

    //查询用户数据
    private void getAccountData(String accountName, MCallBack mCallBack) {
        Random random = new Random();
        boolean isSuccess = random.nextBoolean();
        if (isSuccess) {
            Account account = new Account();
            account.setName(accountName);
            account.setLevel(100);
            mCallBack.onSuccess(account);
        } else {
            mCallBack.onFail();
        }
    }
}

由上述代码可以发现,MainActivity承载了太多的功能,既要实现方法,又要承担逻辑,这样当以后功能越来越多的时候,这个界面的代码就会越来越多,越来越臃肿。

MVC模型简介

MVC的全名是Model View Controller,即模型(Model)-视图(View)-控制器(Controller)。
Controller:Activity,Fragment
View:layout,View控件
Controller:数据处理(网络请求,SQL等)


WX20191121-161628.png

使用MVC实现需求

MVCActivity(C层):业务逻辑处理,获取用户输入,展示成功界面,展示失败界面
MVCModel(M层):查询账号数据
View(V层):layout
1.将数据的获取和界面的展示分离(将查询账号数据从Activity中分离到Model中即可)
2.解决各层之间的通信问题(Activity通知Model获取数据,Model通知Activity更新界面)

public class MVCActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText edittext;
    private Button button;
    private TextView text;
    private MVCModel mvcModel;

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


    private void init() {
        edittext = findViewById(R.id.edittext);
        button = findViewById(R.id.button);
        button.setOnClickListener(this);
        text = findViewById(R.id.text);
        mvcModel = new MVCModel();
    }

    @Override
    public void onClick(View v) {
        mvcModel.getAccountData(getUserInput(), new MCallBack() {
            @Override
            public void onSuccess(Account account) {
                showSuccessPage(account);
            }

            @Override
            public void onFail() {
                showFailPage();
            }
        });
    }

    //获取用户输入信息
    private String getUserInput() {
        return edittext.getText().toString().trim();
    }

    //展示获取信息成功界面
    private void showSuccessPage(Account account) {
        text.setText("用户账号:" + account.getName() + "|" + "用户等级:" + account.getLevel());
    }

    //展示获取信息失败界面
    private void showFailPage() {
        text.setText("获取数据失败");
    }
}
public class MVCModel {
    //查询用户数据
    public void getAccountData(String accountName, MCallBack mCallBack) {
        Random random = new Random();
        boolean isSuccess = random.nextBoolean();
        if (isSuccess) {
            Account account = new Account();
            account.setName(accountName);
            account.setLevel(100);
            mCallBack.onSuccess(account);
        } else {
            mCallBack.onFail();
        }
    }
}

MVC优缺点

优点:一定程度上实现了Model与View的分离,降低了代码的耦合性。

缺点:Controller与View难以完全解耦,并且随着项目复杂度的提升,因为Controller还承担部分业务逻辑,所以Controller将越来越臃肿。

MVP模型简介

MVP即Model_View_Presenter模型


WX20191121-161412.png

MVP与MVC的差别

1.Model与View不再直接进行通信,而是通过中间层Presenter来实现。

  1. Activity的功能被简化,不再充当控制器,主要负责View层面的工作。

MVP代码实战

WX20191121-162447.png

使用MVP实现需求

  1. MVPActivity负责提供View层面的功能(采用实现接口的方式)

2.MVPModel负责提供数据方面的功能

3.Model与View不再直接通信,通过Presenter来实现

public class MVPActivity extends AppCompatActivity implements View.OnClickListener, IMVPView {

    private EditText edittext;
    private Button button;
    private TextView text;
    private MVPPresenter mvpPresenter;

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

    private void init() {
        edittext = findViewById(R.id.edittext);
        button = findViewById(R.id.button);
        button.setOnClickListener(this);
        text = findViewById(R.id.text);
        mvpPresenter = new MVPPresenter(this);
    }

    @Override
    public void onClick(View v) {

        mvpPresenter.getData(getUserInput());
    }

    @Override
    public String getUserInput() {
        return edittext.getText().toString().trim();
    }

    @Override
    public void showSuccessPage(Account account) {
        text.setText("用户账号:" + account.getName() + "|" + "用户等级:" + account.getLevel());
    }

    @Override
    public void showFailPage() {
        text.setText("获取数据失败");
    }
}
public interface IMVPView {

    String getUserInput();

    void showSuccessPage(Account account);

    void showFailPage();
}

public class MVPModel {
    //查询用户数据
    public void getAccountData(String accountName, MCallBack mCallBack) {
        Random random = new Random();
        boolean isSuccess = random.nextBoolean();
        if (isSuccess) {
            Account account = new Account();
            account.setName(accountName);
            account.setLevel(100);
            mCallBack.onSuccess(account);
        } else {
            mCallBack.onFail();
        }
    }
}

public class MVPPresenter {
    private IMVPView imvpView;
    private MVPModel mvpModel;

    public MVPPresenter(IMVPView imvpView) {
        this.imvpView = imvpView;
        mvpModel = new MVPModel();
    }

    public void getData(String accountName) {
        mvpModel.getAccountData(accountName, new MCallBack() {
            @Override
            public void onSuccess(Account account) {
                imvpView.showSuccessPage(account);
            }

            @Override
            public void onFail() {
                imvpView.showFailPage();
            }
        });
    }

}
 

MVP优缺点

优点:解决了MVC中Controller与View过度耦合的缺点,职责划分明显,更加易于维护。

缺点:接口数量多,项目复杂度升高。随着项目复杂度的提升,Presenter层将越来越臃肿。

使用MVP的建议

1.接口规范化(封装父类接口以减少接口的使用量)
2.使用第三方插件自动生成MVP代码
3.对于一些简单的界面,可以选择不使用框架
4.根据项目复杂程度,部分模块可以选择不使用接口

MVVM模型简介

WX20191121-165818.png

MVVM是Model-View-ViewModel的简写,MVVM在MVP的基础上实现了数据视图的绑定(DataBinding),当数据变化时,视图会自动更新;反之,当视图发生变化时,数据也会自动更新。
1.减少了接口数量
2.告别繁琐findViewById操作

DataBinding是什么

DataBinding是谷歌官方发布的一个实现数据绑定的框架(实现数据与视图双向绑定),DataBinding可以帮助我们在安卓中更好的实现MVVM模式。

DataBinding使用步骤

1.启用DataBinding
2.修改布局文件为DataBinding布局
3.数据绑定

使用MVVM实现需求

WX20191126-155005.png

1.提供View,ViewModel以及Model三层
2.将布局修改为DataBinding布局

  1. View与ViewModel之间通过DataBinding进行通信
  2. 获取数据并展示在界面上
public class MVVMActivity extends AppCompatActivity {

    private MVVMViewModel mvvmViewModel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMvvmBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_mvvm);
        mvvmViewModel = new MVVMViewModel(getApplication(),binding);
        binding.setViewModel(mvvmViewModel);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="com.test.myapplication.mvvm.MVVMViewModel"/>
    </data>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <EditText
            android:id="@+id/edittext"
            android:text="@={viewModel.userInput}"
            android:hint="请输入要查询的账号"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <Button
            android:layout_gravity="center"
            android:id="@+id/button"
            android:text="获取账号信息"
            android:onClick="@{viewModel.getData}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/text"
            android:layout_marginTop="50dp"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewModel.result}"
            android:hint="账号信息未获取" />
    </LinearLayout>
</layout>
public class MVVMViewModel extends BaseObservable {

    private String result;
    private String userInput;
    private MVVMModel model;
    private ActivityMvvmBinding binding;

    //一般需要传入Application对象,方便在ViewModel中使用application
    //比如sharepreferences
    public MVVMViewModel(Application application) {
        model = new MVVMModel();
    }

    public MVVMViewModel(Application application, ActivityMvvmBinding binding) {
        model = new MVVMModel();
        this.binding = binding;
    }

    public void getData(View view) {

        model.getAccountData(userInput, new MCallBack() {
            @Override
            public void onSuccess(Account account) {
                String info = "用户账号:" + account.getName() + "|" + "用户等级:" + account.getLevel();
                setResult(info);
            }

            @Override
            public void onFail() {
                setResult("获取数据失败");
            }
        });
    }

    @Bindable
    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
        notifyPropertyChanged(BR.result);
    }

    @Bindable
    public String getUserInput() {
        return userInput;
    }

    public void setUserInput(String userInput) {
        this.userInput = userInput;
        notifyPropertyChanged(BR.userInput);
    }
}
public class MVVMModel {
    //查询用户数据
    public void getAccountData(String accountName, MCallBack mCallBack) {
        Random random = new Random();
        boolean isSuccess = random.nextBoolean();
        if (isSuccess) {
            Account account = new Account();
            account.setName(accountName);
            account.setLevel(100);
            mCallBack.onSuccess(account);
        } else {
            mCallBack.onFail();
        }
    }
}

MVVM优缺点

优点:实现了数据和视图的双向绑定,极大的简化代码。

缺点:bug难以调试,并且DataBinding目前还存在一些编译问题。

上一篇 下一篇

猜你喜欢

热点阅读