Android设计架构:MVC、MVP、MVVM架构详解

主要分析这几个架构的特性,优缺点,以及App架构设计中应该注意的问题
1、MVC设计架构(Model-View-Controller)
(1)简介:MVC全名是Model View Controller,是模型,视图,控制器的缩写,用一种业务逻辑,数据,界面显示分离的方法组织代码,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑(M层处理数据,业务逻辑等;V层处理界面的显示结果;C层起到桥梁作用,来控制V层和M层通信以此来达到分离视图显示和业务逻辑层)
(2)Android中的MVC
视图层(View)
一般采用XML文件进行界面的描述,这些XML可以理解为View,使用的时候可以非常方便的引入。同时便于后期界面的修改。逻辑中界面对应的id不变则代码不用修改,大大增加了代码的可维护性。
模型层(Model)
针对业务模型,建立的数据结构和相关的类,就可以理解为Model,Model是与View无关,而与业务相关的。
控制层(Controller)
控制层通常是Activity,不要再Activity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另一个原因是Android中的Activity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
(3)总结:(用户)→ (View)→ (Activity)→ (Model)→ (Activity)→ (View)→ (用户)
(4)MVC的缺点: 在Android开发中,Activity并不是一个标准的MVC模式中的Controller,它的首要职责是加载应用的布局和初始化用户界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。
2、MVP设计架构(Model-View-Presenter)
(1)简介:MVP从更早的MVC框架演变过来,与MVC有一定的相似性:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。
View→ Presenter→ Model→ Presenter→ View
MVP框架由3部分组成:View负责显示,Presenter负责逻辑处理,Model提供数据。在MVP模式里通常包含3个要素(加上View interface是4个)
View:负责绘制UI元素,与用户进行交互(在Android中体现为Activity)
Model:负责存储,检索,操纵数据(有时也实现一个Model interface用来降低耦合)
Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑
View interface:需要VIiew实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试
(2)View interface的必要性
在MVP模式中,处理复杂逻辑的Presenter是通过interface与View(Activity)进行交互的,这说明我们可以通过自定义类实现这个interface来模拟Activity的行为对Presenter进行单元测试,省去了大量的部署及测试时间。
(3) 具体到AndroidApp中,一般可以将App根据程序的结构进行纵向划分,根据MVP可以将App分别为模型层(M),UI层(V)和逻辑层(P)。
UI层一般包括Activity,Fragment,Adapter等直接和UI相关的类,UI层的Activity在启动之后实例化相应的Presenter,App的控制权后移,由UI转移到Presenter,两者之间的通信通过BroadCast、Handler或者接口完成,只传递事件和结果。
举例: UI层通知逻辑层(Presenter)用户点击了一个Button,逻辑层(Presenter)自己决定应该用什么行为进行响应,该找哪个模型(Model)去做这件事,最后逻辑层(Presenter)将完成的结果更新到UI层。
(4)MVP的优点
在MVP中,Activity的代码不臃肿;
在MVP中,Model(IUserModel的实现类)的改动不会影响Activity(View),两者也互不干涉,而在MVC中会;
在MVP中,IUserView这个接口可以实现方便地对Presenter的测试;
在MVP中,UserPresenter可以用于多个视图,但是在MVC中的Activity就不行。
代码如下:
(一)View(Presenter与View交互是通过接口实现的,所以我们需要定义一个接口IUserView(难点在于IUserView中应该有哪些方法))

public interface IUserView {
    String getUserName();
    String getPassWord();
    void toMainActivity(User user);
    void showFailedError();
}
public class UserActivity extends Activity implements View.OnClickListener, IUserView{

    private TextView tv_password;
    private TextView tv_username;
    private Button btn_login;
    private UserPresenter userPresenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mvp_user);
        tv_password = (TextView) findViewById(R.id.tv_password);
        tv_username = (TextView) findViewById(R.id.tv_username);
        btn_login = (Button) findViewById(R.id.btn_login);
        btn_login.setOnClickListener(this);
        userPresenter = new UserPresenter(this);
    }

    @Override
    public void onClick(View v) {
        userPresenter.login();
    }

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

    @Override
    public String getPassWord() {
        return tv_password.getText().toString();
    }

    @Override
    public void toMainActivity(User user) {
        Log.i("loginSuccess", "username" + user.getUsername() + ": password" + user.getPassword());
    }

    @Override
    public void showFailedError() {
        Log.i("loginSuccess", "登录失败");
    }
}

(二)Model(抽取一个业务类接口IUserModel和一个返回是否成功接口OnLoginListener)

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;
    }
}
public interface IUserModel {
    void login(String username, String password, OnLoginListener onLoginListener);
}
public interface OnLoginListener {
    void loginSuccess(User user);
    void loginFailed();
}
public class UserModel implements IUserModel{
    @Override
    public void login(String username, String password, OnLoginListener onLoginListener) {
        if ("zhy".equals(username) && "123".equals(password))
        {
            User user = new User();
            user.setUsername(username);
            user.setPassword(password);
            onLoginListener.loginSuccess(user);
        } else
        {
            onLoginListener.loginFailed();
        }
    }
}

(三)Presenter(我们的presenter完成二者的交互,那么肯定需要二者的实现类。大致就是从View中获取需要的参数,交给Model去执行业务方法,执行的过程中需要的反馈,以及结果,再让View进行做对应的显示。)

public class UserPresenter{
    private UserModel userModel;
    private IUserView iUserView;

    public UserPresenter(IUserView iUserView){
        this.iUserView = iUserView;
    }
    public void login(){
        userModel = new UserModel();
        userModel.login(iUserView.getUserName(), iUserView.getPassWord(), new OnLoginListener() {
            @Override
            public void loginSuccess(User user) {
                iUserView.toMainActivity(user);
            }

            @Override
            public void loginFailed() {
                iUserView.showFailedError();
            }
        });
    }
}

3、MVVM设计模式(Model,View,ViewModel)
在MVP中,我们需要Model,View,Presenter三样进行配合使用,但是在View中还是会出现大量的类似ShowLoad之类的代码,而这在MVVM是由Model,View,ViewModel进行配合的。其中主要区别在于ViewModel,Data Binding 的奇妙之处在于可以将 XML 文件与指定的 JAVA 类绑定 , 实现数据自动更新的效果 .
使用步骤
1.在build.gradle文件中添加如下部分

dataBinding{
     enabled = true
 }

2.在XML文件中

<layout xmlns:android="http://schemas.android.com/apk/res/android">
  <data>
    <variable
        name="user"
        type="com.shire.mvvmdemo.viewModel.User"/>
  </data>
  <RelativeLayout
            android:id="@+id/rl_time"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/tv_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="15dp"
                android:layout_marginLeft="15dp"
                android:layout_marginTop="15dp"
                android:text="@{user.username}"
                android:textColor="#555555"
                android:textSize="18dp" />

            <TextView
                android:id="@+id/tv_workShift"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_marginRight="15dp"
                android:layout_marginTop="10dp"
                android:text="@{user.password}"
                android:textColor="#999999"
                android:textSize="9dp" />

            <View
                android:layout_width="match_parent"
                android:layout_height="@dimen/sizeLine"
                android:layout_below="@id/tv_time"
                android:background="@color/colorLine" />
        </RelativeLayout>
</layout>

根节点是layout
3.在activity文件中

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.setUser(new User("123","123"));
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_34413065/article/details/87029117