Android App的设计架构:MVC、MVP、MVVM的实现

目的

通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合。这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点,提高程序开发的效率,并且更容易进行后续的测试以及定位问题。但设计不能违背目的,对于不同量级的工程,具体架构的实现方式必然是不同的,切忌犯为了设计而设计,为了架构而架构的毛病。

一、MVC模式

MVC全名是Model View Controller,如图,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。

其中M层处理数据,业务逻辑等;V层处理界面的显示结果;C层起到桥梁的作用,来控制V层和M层通信以此来达到分离视图显示和业务逻辑层。

在这里插入图片描述

Android中的MVC

Android中界面部分也采用了当前比较流行的MVC框架,在Android中:

  • 视图层(View)

一般采用XML文件进行界面的描述,这些XML可以理解为AndroidApp的View。使用的时候可以非常方便的引入。同时便于后期界面的修改。逻辑中与界面对应的id不变化则代码不用修改,大大增强了代码的可维护性。

  • 控制层(Controller)

Android的控制层的重任通常落在了众多的Activity的肩上。这句话也就暗含了不要在Activity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Actiivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。

  • 模型层(Model)

我们针对业务模型,建立的数据结构和相关的类,就可以理解为AndroidApp的Model,Model是与View无关,而与业务相关的。对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。

示例

视图层(View)
在Android开发中,xml布局文件就相当于视图层。
在这里插入图片描述
控制层(Controller)

public class MainActivity extends Activity implements OnWeatherListener{

    private WeatherModel weatherModel;
    private EditText cityNOInput;
    private TextView city;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        weatherModel = new WeatherModelImpl();
        initView();
    }

    //初始化View
    private void initView() {
        cityNOInput = findViewById(R.id.et_city_no);
        city = findViewById(R.id.tv_city).setOnClickListener((view)->{
        	  weatherModel.getWeather(cityNOInput.getText().toString().trim(), this);
        });
    }


    @Override
    public void onSuccess(Weather weather) {
        displayResult(weather);
    }

    @Override
    public void onError() {
        Toast.makeText(this, 获取天气信息失败, Toast.LENGTH_SHORT).show();
    }

    //显示结果
    public void displayResult(Weather weather) {
        WeatherInfo weatherInfo = weather.getWeatherinfo();
        city.setText(weatherInfo.getCity());
    }
}

模型层(Model)

public interface WeatherModel {
    void getWeather(String cityNumber, OnWeatherListener listener);
}

public interface OnWeatherListener{
    void onSuccess(Weather weather);
    void onError();
}


public class WeatherModelImpl implements WeatherModel {
    /*这部分代码范例有问题,网络访问不应该在Model中,应该把网络访问换成从数据库读取*/
    @Override
    public void getWeather(String cityNumber, final OnWeatherListener listener) {

        /*数据层操作*/
        VolleyRequest.newInstance().newGsonRequest(http://www.weather.com.cn/data/sk/ + cityNumber + .html,
                Weather.class, new Response.Listener<weather>() {
                    @Override
                    public void onResponse(Weather weather) {
                        if (weather != null) {
                            listener.onSuccess(weather);
                        } else {
                            listener.onError();
                        }
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        listener.onError();
                    }
                });
    }
}

上面的例子可以看到,通过View既txml布局文件展示界面,由Controller监听View的行为,当点击按钮后,控制Model获取以及处理数据,再将得到的数据传给Controller,由Controller控制界面展示新的数据。

在Android中Activty也充当着View的角色,M层是独立出来的,V层和C层的角色都由Activity来承担。导致View和Controller难以分离,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。

二、MVP模式

在Android开发中,Activity并不是一个标准的MVC模式中的Controller,它的首要职责是加载应用的布局和初始化用户 界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。

MVP从更早的MVC框架演变过来,与MVC有一定的相似性:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。
在这里插入图片描述MVP框架由3部分组成:View负责显示,Presenter负责逻辑处理,Model提供数据。在MVP模式里通常包含3个要素(加上View interface是4个):

  • View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity)
  • Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合)
  • Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
  • View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试
  1. 各部分之间的通信,都是双向的。
  2. View 与 Model 不发生联系,都通过 Presenter 传递。
  3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。

示例

模型层(Model)

建立Bean

public class UserBean {
     private String mFirstName;
     private String mLastName;
     public UserBean(String firstName, String lastName) {
            this. mFirstName = firstName;
            this. mLastName = lastName;
     }
     public String getFirstName() {
            return mFirstName;
     }
     public String getLastName() {
            return mLastName;
     }
}

建立Model
先写接口,后写实现,实现不在这里写了(处理业务逻辑,这里指数据读写)

public interface IUserModel {
     void setID(int id);

     void setFirstName(String firstName);

     void setLastName(String lastName);

     int getID();

     UserBean load(int id);// 通过id读取user信息,返回一个UserBean
}

控制层(Presenter)
建立presenter,通过iView和iModel接口操作model和view,activity可以把所有逻辑给presenter处理,这样java逻辑就从手机的activity中分离出来。

public class UserPresenter {
     private IUserView mUserView;
     private IUserModel mUserModel;

     public UserPresenter(IUserView view) {
            mUserView = view;
            mUserModel = new UserModel();
     }

     public void saveUser( int id, String firstName, String lastName) {
            mUserModel.setID(id);
            mUserModel.setFirstName(firstName);
            mUserModel.setLastName(lastName);
     }

     public void loadUser( int id) {
           UserBean user = mUserModel.load(id);
            mUserView.setFirstName(user.getFirstName()); // 通过调用IUserView的方法来更新显示
            mUserView.setLastName(user.getLastName());
     }
}

视图层(View)
建立view的接口,这里列出需要操作当前view的方法。

public interface IUserView {
     int getID();

     String getFristName();

     String getLastName();

     void setFirstName(String firstName);

     void setLastName(String lastName);
}

activity中实现iview接口,在其中操作view,实例化一个presenter变量。

public class MainActivity extends Activity implements OnClickListener,IUserView {

     UserPresenter presenter;
     EditText id,first,last;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
           setContentView(R.layout. activity_main);

           findViewById(R.id. save).setOnClickListener( this);
           findViewById(R.id. load).setOnClickListener( this);
            id = (EditText) findViewById(R.id. id);
            first = (EditText) findViewById(R.id. first);
            last = (EditText) findViewById(R.id. last);

            presenter = new UserPresenter( this);
     }

     @Override
     public void onClick(View v) {
            switch (v.getId()) {
            case R.id. save:
                 presenter.saveUser(getID(), getFristName(), getLastName());
                 break;
            case R.id. load:
                 presenter.loadUser(getID());
                 break;
            default:
                 break;
           }
     }

     @Override
     public int getID() {
            return new Integer( id.getText().toString());
     }

     @Override
     public String getFristName() {
            return first.getText().toString();
     }

     @Override
     public String getLastName() {
            return last.getText().toString();
     }

     @Override
     public void setFirstName(String firstName) {
            first.setText(firstName);
     }

     @Override
     public void setLastName(String lastName) {
            last.setText(lastName);
     }

}

因此,Activity及从MVC中的Controller中解放出来了,这会Activity主要做显示View的作用和用户交互。每个Activity可以根据自己显示View的不同实现View视图接口IUserView。

三、MVVM模式

MVVM是Model-View-ViewModel的简写,MVVM可以算是MVP的升级版,其中的VM是ViewModel的缩写,ViewModel可以理解成是View的数据模型和Presenter的合体,他的关键技术就是Data Binding,ViewModel和View之间的交互通过Data Binding完成。View的变化可以自动的反应在ViewModel,ViewModel的数据变化也会自动反应到View上。这样开发者就不用处理接收事件和View更新的工作,框架已经帮你做好了。
在这里插入图片描述

  • Model:数据层,负责处理数据的加载或者存储
  • View:视图层,负责界面数据的展示,与用户进行交互
  • ViewModel:负责完成View于Model间的交互,负责业务逻辑

Data Binding Library

对于Data Binding的使用,可以参考这两篇文章:
Android Data Binding数据绑定详解(基础篇)
Android Data Binding数据绑定详解(进阶篇)

发布了63 篇原创文章 · 获赞 1 · 访问量 2101

猜你喜欢

转载自blog.csdn.net/weixin_42046829/article/details/104951571