mvp架构模式

作者: 山野纸鹤 | 来源:发表于2016-10-01 17:55 被阅读481次

    ​今天是国庆节,祝大家节日快乐,愿祖国越发繁荣昌盛。假期程序员也不能偷懒,更新一些博文吧。

    mvp指的是现在Android开发中比较常见的一种软件架构模式。mvp架构模式是Google官方推荐的架构模式,特别是近年来的新项目,mvp+retrofit+rxjava+dragger2配合使用已经在引领程序界的潮流了,在github上可以轻易的搜到一大堆这样的开源项目。前端时间笔者也在公司的一个sdk上进行了尝试,在此算是做个简单的总结吧。本文主要介绍什么是mvp架构模式,还有这种架构模式的优势以及如何使用它搭建你的项目。

    一、mvp为何物

    我之前在公司项目中做尝试的时候,提交代码后公司同事曾问过我这个问题,

    我当时作了个简单的解释,这也是我学习过程中总结出来的,如果要做一个比较正规的定义,我觉得应该这么说:mvp 是从经典的mvc模式演变过来的,其基本思路都是相通的。其中M是model模型,提供业务数据;P是Presenter控制者,进行逻辑处理。V是View视图,显示数据。在MVP中View并不直接使用Model,它们之间的通信是通过Presenter 来进行的,所有的交互都发生在Presener内部。在笔者的世界里,mvp架构模式的定义就是这样的,如果你看到这里觉得难以接受这个定义,或者你认为这是错误的观点,就不建议你继续往下看了,建议直接留言联系笔者进行探讨。

    二、mvp架构模式的优势

    如果你读到这里,说明你应该是已经接受笔者对mvp架构模式的定义了。接下来要阐述的是mvp架构模式的优势。众所周知,Android原生应用开发使用的是Java语言(至少目前绝大多数是),Java语言是面向对象的,面向对象的六大原则其中之一是单一职责原则,它的官方定义是There should never be more than one reason for a class to change,应该有且仅有一个原因引起类的变更。说到底就是解耦合。对,解耦合,这就是mvp架构模式的终极目标,也是它最大的优势。为什么要把架构里的各个层次分得清清楚楚,每个层面负责什么,不应该负责负责,如何组合起来都需要严格的定义起来,你要知道,每一种架构都不是编码规范,也不是组织代码的规范,它们都是一种思维方式。所以在实践中你永远要记住你为什么使用mvp架构模式,切忌忘记初衷,为了炫酷而在使用mvp。

    三、mvp架构模式的简单实践

    没错,在码农的世界里任何语言都是苍白无力的,还是代码来的实际。稍安勿躁,代码马上就来。但是还是要提醒大家,只会写代码的不叫程序员,叫代码搬运工(就是搬砖的),学会编程之后就要升华一下,去掌握编程思想,以让你的代码更优雅,这句话是前几天老大跟我说的,在此送给大家。

    为演示mvp架构模式的使用,笔者写了一个简单的小demo,demo主要功能是去服务器请求App版本更新的信息,服务器会返回版本信息,包括最新版本名,一个提示字段,还有是否需要更新的字段,将返回的数据封装Version实体类,代码如下:

    public classVersion {

    //是否有新版本

    privateStringhasNewVersion;

    //描述

    privateStringdesc;

    //最新版本名

    privateStringlatest_version;

    publicStringgetHasNewVersion() {

    returnhasNewVersion;

    }

    publicStringgetDesc() {

    returndesc;

    }

    publicStringgetLatest_version() {

    returnlatest_version;

    }

    public voidsetHasNewVersion(String hasNewVersion) {

    this.hasNewVersion= hasNewVersion;

    }

    public voidsetDesc(String desc) {

    this.desc= desc;

    }

    public voidsetLatest_version(String latest_version) {

    this.latest_version= latest_version;

    }

    }

    主界面有两个TextView,一个用于显示版本名,一个用于显示版本的描述,还有一个按钮,点击按钮会触发请求,代码如下:

    public classVersionActivityextendsAppCompatActivityimplementsVersionView{

    privateTextViewtv_versionName;

    privateTextViewtv_desc;

    privateVersionPresentermVersionPresenter;

    @Override

    protected voidonCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_mvp);

    mVersionPresenter=VersionPresenter.getInstance(this,this);

    tv_desc=(TextView) findViewById(R.id.tv_desc);

    tv_versionName=(TextView) findViewById(R.id.tv_versionname);

    findViewById(R.id.tv_but).setOnClickListener(newView.OnClickListener() {

    @Override

    public voidonClick(View v) {

    mVersionPresenter.getNewVersion("http://10.180.152.101:8080/NetWorkServer/updateappversion"+"?currentversion=1.4");

    }

    });

    }

    @Override

    public voidshowVersionNameAndDesc(Version version) {

    tv_versionName.setText("最新版本名: "+version.getLatest_version());

    tv_desc.setText(version.getDesc());

    }

    @Override

    public voidshowToast(String msg) {

    Toast.makeText(VersionActivity.this,msg,Toast.LENGTH_LONG).show();

    }

    }

    该Activity实现了VersionView接口,这就是mvp中的view层,用于跟用户交互,显示数据。我们可以看到VersionPresenter的初始化,VersionPresenter属于presenter层,用于处理view与model层的通信,不让view直接操作model,可见用户点击按钮后,就通知VersionPresenter去获取版本信息,至于如何获取版本信息,presenter层会交给对应的model去进行处理,下面是VersionPresenter的代码:

    public classVersionPresenterextendsIPresenter {

    private staticVersionPresentermVersionPresenter;

    privateVersionModelmVersionModel;

    privateVersionViewmVersionView;

    privateContextmContext;

    privateVersionPresenter(Context context,IView view){

    this.mContext=context;

    this.mVersionView=(VersionView) view;

    this.mVersionModel=newVersionModel();

    }

    public staticVersionPresentergetInstance(Context context,VersionView view){

    if(mVersionPresenter==null){

    synchronized(VersionPresenter.class){

    if(mVersionPresenter==null){

    mVersionPresenter=newVersionPresenter(context,view);

    }

    }

    }

    returnmVersionPresenter;

    }

    //获取最新版本

    public voidgetNewVersion(String url){

    mVersionModel.getNewVersion(mContext,url, newVersionModel.VersionCallback() {

    @Override

    public voidonVersionCallback(finalVersion version) {

    ((Activity)mContext).runOnUiThread(newRunnable() {

    @Override

    public voidrun() {

    mVersionView.showVersionNameAndDesc(version);

    if(version.getHasNewVersion().equals("true")){

    mVersionView.showToast("App有新版本,请更新");

    }

    }

    });

    }

    });

    }

    }

    用户通知presenter后,presenter就把view的需求通知model层,数据操作交给model层去做具体实现,可以见到在VersionPresenter的getNewVersion方法中只是把view传过来的参数给到model,具体的网络请求交给VersionModel去实现,下面是VersionModel的具体实现:

    public classVersionModelimplementsIModel {

    public interfaceVersionCallback {

    voidonVersionCallback(Version version);

    }

    privateHttpURLConnectionhttpURLConnection=null;

    privateInputStreaminputStream=null;

    privateBufferedReaderbufferedReader=null;

    public voidgetNewVersion(Context context,finalString url, finalVersionCallback versionCallback) {

    newThread(newRunnable() {

    @Override

    public voidrun() {

    try{

    httpURLConnection= (HttpURLConnection)newURL(url).openConnection();

    httpURLConnection.connect();

    inputStream=httpURLConnection.getInputStream();

    bufferedReader=newBufferedReader(newInputStreamReader(inputStream,"utf-8"));

    StringBuilder stringBuilder =newStringBuilder();

    String tempLine =null;

    while((tempLine =bufferedReader.readLine()) !=null) {

    stringBuilder.append(tempLine).append("\n");

    }

    String data = stringBuilder.toString();

    Log.e("data",data);

    JSONObject jsonObject=null;

    jsonObject =newJSONObject(data);

    Version version=newVersion();

    version.setLatest_version(jsonObject.optString("latest_version"));

    version.setDesc(jsonObject.optString("desc"));

    version.setHasNewVersion(jsonObject.optString("hasNewVersion"));

    versionCallback.onVersionCallback(version);

    }catch(Exception e) {

    e.printStackTrace();

    }finally{

    try{

    bufferedReader.close();

    inputStream.close();

    }catch(Exception e) {

    }

    }

    }

    }).start();

    }

    }

    VersionModel去执行网络请求,获取到VersonView需要的数据然后回调到VersionPresenter,再由VersionPresenter通知VersonView去做UI的变化或者其他一些操作。纵观整个过程可以发现,view层和model层没有一丝耦合,这就是mvp架构模式的初衷,做到了松耦合,view,model,presenter每一层负责自身的工作,绝不越界。

    总结

    由于服务器代码也是自己写的,只有一个请求接口,数据的交互也很简单,但是麻雀虽小五脏俱全,服务器端跟客户端都在尽量模拟实际开发中的流程,真个mvp架构模式的基本流程都有了,在此也附上源码地址,源码中有服务器和客户端的代码:GitHub - shanyezhihe/mvpdemo

    扫码关注公众号

    相关文章

      网友评论

      • 阿吹md:代码虽多,但是看不下去啊
        山野纸鹤:@阿吹md sorry,代码排版不好,建议直接关注公众号,获取最新文章查看,以后会注意这个问题,谢谢。
      • guodongAndroid:把代码排好版定能实现作家梦
        山野纸鹤: @guodongAndroid 谢谢指正,下次会注意😊
      • fendo:赞一个!!
        山野纸鹤: @fendo 谢谢,可以扫码关注公号哦

      本文标题:mvp架构模式

      本文链接:https://www.haomeiwen.com/subject/ypgryttx.html