Android项目中,尤其是比较大型的项目开发中,模块内部的高聚合和模块间的低耦合性就显得尤为重要了。所以我们一般情况下需要为项目设计一种框架模式,通常情况下我们一般用到的三种MVCMVPMVVM
通过框架模式设计的项目能够极大的提高开发效率,提高项目的可维护性和可扩展性,另外在模块测试及问题定位上也提供了较大的便利。

接下来我们就对这三种框架模式一一进行讲解,并会重点讲解下比较常用的MVP框架模式。

一、MVC框架:

图片源自网络

MVC全称为Model(模型层)--View(视图层)--Controller(控制层)。
    Model层:主要用于网络请求、数据库、业务逻辑处理等操作。
    View层:用于展示UI,一般采用XML文件进行界面的描述。
    Controller层:控制层的重任落在了众多Activity上,Activity需要交割业务逻辑至Model层处理。

下面结合精简的实例来看下MVC框架模式:

1、View层&Controller层

View层:XML布局文件activity_mvcpattern代表的就是View层,用来显示布局,与用户进行交互。

Controller层:MVCActivity代表的是Controller层,View层会传递请求至Controller,Controller控制Model层进行业务的更新。


/*** @author hongri* @date 2018/9/4** Controller层*/
public class MVCActivity extends AppCompatActivity implements View.OnClickListener {private Button btnRequest;private ImageView iv;private MVCHttpRequestModel mvcHttpRequestModel;private static final String requestUrl = "https://avatar.csdnimg.cn/5/7/C/1_u012440207.jpg";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);/*** xml文件属于理论上的View层*/setContentView(R.layout.activity_mvcpattern);mvcHttpRequestModel = new MVCHttpRequestModel();btnRequest = findViewById(R.id.btnRequest);iv = findViewById(R.id.iv);btnRequest.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btnRequest:/*** Controller层将网络请求业务逻辑交由Model层处理*/mvcHttpRequestModel.onHttpRequest(requestUrl, new MVCRequestCallback() {@Overridepublic void onSuccess(Object successData) {if (successData != null) {iv.setImageBitmap((Bitmap)successData);}}@Overridepublic void onFailure(Object failureData) {Toast.makeText(MVCActivity.this, failureData.toString(), Toast.LENGTH_LONG).show();}});break;default:break;}}
}

2、Model层:

这里的MVCHttpRequestModel便属于Model层,Model层主要用于处理数据库、网络请求等一系列复杂的耗时处理,Model数据请求完成后,通知View进行UI的更新。

/*** @author hongri* @date 2018/9/4** Model层*/public class MVCHttpRequestModel implements MVCHttpRequestInterface {@Overridepublic void onHttpRequest(final String urlString, final MVCRequestCallback listener) {new RequestTask(listener).execute(urlString);}public class RequestTask extends AsyncTask<String, Void, Bitmap> {private MVCRequestCallback listener;public RequestTask(MVCRequestCallback listener) {this.listener = listener;}@Overrideprotected Bitmap doInBackground(String... strings) {Bitmap bitmap = null;InputStream inputStream;try {URL url = new URL(strings[0]);HttpURLConnection conn = (HttpURLConnection)url.openConnection();conn.setRequestMethod("GET");conn.setConnectTimeout(10 * 1000);int responseCode = conn.getResponseCode();if (responseCode == 200) {inputStream = conn.getInputStream();bitmap = BitmapFactory.decodeStream(inputStream);} else {bitmap = null;}} catch (IOException e) {e.printStackTrace();}return bitmap;}@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);/***Model层请求完数据后回调给Controller层,Controller层更新UI*/if (bitmap != null) {listener.onSuccess(bitmap);} else {listener.onFailure("获取失败");}}}
}

二、MVP框架

图片源自网络

MVP全称为Model(模型层)--View(视图层)--Presenter(协调器/主持者)

MVP是由MVC转化而来的一种框架模式,MVP相比于MVC具有的优点如下:

1、Model层与View层完全分离,我们可以修改视图而不影响模型;

2、可以更高效地使用模型,因为所有的交互都发生在一个地方---Presenter内部;

3、可以将大量的逻辑操作放到Presenter中,避免Activity的臃肿;

4、可以选择将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。

下面根据代码来具体介绍下MVP框架:

1、View层:

View层一般由多个Activity来承担,主要用于显示UI,与用户来进行交互。

/*** MVP(Model--View--Presenter)框架模式--参考:http://www.jcodecraeer.com/a/anzhuokaifa/2017/1020/8625.html** @author hongri** View层*/
public class MVPActivity extends MVPBaseActivity implements MVPViewInterface, OnClickListener {private Button btnName;private TextView tvData;private MVPPresenter mvpPresenter;private String requestUrl = "";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_mvppattern);mvpPresenter = new MVPPresenter();mvpPresenter.attachView(this);btnName = findViewById(R.id.btnName);tvData = findViewById(R.id.tvData);btnName.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btnName:tvData.setText("初始数据");mvpPresenter.requestData(requestUrl);break;default:break;}}@Overridepublic void showSuccessData(String data) {MVPDataInfo dataInfo = ParseJsonUtil.parseJSONData(data);tvData.setText("姓名:" + dataInfo.getmName() + "\n" + "性别:" + dataInfo.getmGender() + "\n" + "年龄:" + dataInfo.getmAge());}@Overridepublic void showFailureData(String data) {tvData.setText(data);}@Overrideprotected void onDestroy() {super.onDestroy();if (mvpPresenter != null) {mvpPresenter.detachView();}}
}

这里为MVPActivity设置了一个顶级父类MVPBaseActivity,父类Activity中可以提炼出公用的UI展示、初始化等操作,减少各子Activity的冗余代码,也方便后续的维护。

/*** @author hongri* BaseActivity用于进行View层的通用的初始化及UI展示工作*/
public class MVPBaseActivity extends AppCompatActivity implements MVPBaseViewInterface {/*** 页面通用LoadingDialog*/private LoadingDialog loadingDialog;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_mvpbase);loadingDialog = new LoadingDialog(this, R.style.LoadingTheme);}@Overridepublic void showLoading() {if (loadingDialog != null) {loadingDialog.showLoading();}}@Overridepublic void dismissLoading() {if (loadingDialog != null) {loadingDialog.dismissLoading();}}
}

接口也采用Base层继承的方式,分别定义了MVPViewInterface,及MVPBaseViewInterface,分别用于MVPActivity及MVPBaseActivity的回调,其中子接口根据业务区别一般是需要建立多个的。

/*** @author hongri* @date 2018/9/4** 记录某个业务方所需的回调方法*/public interface MVPViewInterface extends MVPBaseViewInterface {/*** 业务方数据成功获取后,调用此方法更新UI** @param data*/void showSuccessData(String data);/*** 业务方数据获取失败后,调用此方法展示失败页面UI** @param data*/void showFailureData(String data);}

/*** @author hongri* @date 2018/9/3** 该接口记录所有页面通用的回调方法*/public interface MVPBaseViewInterface {/*** 展示通用页面Loading*/void showLoading();/*** 取消通用页面Loading*/void dismissLoading();
}

2、Presenter层:

Presenter层主要用于业务逻辑操作,避免了Activity的代码臃肿。

/*** @author hongri* @date 2018/9/3** Presenter层*/public class MVPPresenter extends MVPBasePresenter<MVPViewInterface> implements MVPLoadDataCallback {/*** 请求数据入口** @param url*/public void requestData(String url) {getAttachView().showLoading();MVPDataModelManager.newInstance(MVPDataModel.class.getName()).setParams("").executeGetRequest(url, this);}/*** 数据请求成功--更新UI** @param successData*/@Overridepublic void onSuccess(String successData) {if (isViewAttached()) {getAttachView().dismissLoading();getAttachView().showSuccessData(successData);}}/*** 数据请求失败--更新展示错误页面UI** @param errorData*/@Overridepublic void onFailure(String errorData) {if (isViewAttached()) {getAttachView().dismissLoading();getAttachView().showFailureData(errorData);}}
}
/*** @author hongri* @date 2018/9/4*/public class MVPBasePresenter<V extends MVPBaseViewInterface> {public V mView;/*** 绑定mView,一般在初始化中调用该方法*/public void attachView(V view) {mView = view;}/*** 销毁mView,一般在onDestroy方法中调用*/public void detachView() {if (mView != null) {mView = null;}}/*** 是否与mView建立联系* 每次调用业务方请求的时候都要先调用此方法检查是否与mView建立联系*/public boolean isViewAttached() {return mView != null;}/*** 获取连接的mView*/public V getAttachView() {return mView;}
}

3、Model层:

该Model层与MVC模式中的Model层类似,项目中所有数据都由该类流入和流出,负责分发所有的请求数据。

/*** @author hongri* @date 2018/9/3** Model层*/public class MVPDataModel extends MVPBaseModel {public String data = "";@Overridepublic void executeGetRequest(String url, final MVPLoadDataCallback callback) {/*** 模拟网络请求耗时操作*/new Handler().postDelayed(new Runnable() {@Overridepublic void run() {/*** 从服务端请求回来的字符串数据:* 为了增加通用性,建议以请求回来的原有数据返回给View层,由View层做具体的数据解析、UI展示处理*/data = "{\n"+ "  \"mData\":\"红日\",\n"+ "  \"gender\": \"男士\",\n"+ "  \"age\":18\n"+ "}";if (!TextUtils.isEmpty(data)) {callback.onSuccess(data);} else {data = "数据获取失败";callback.onFailure(data);}}}, 1000);}
}

这里也封装了一个父类base层--MVPBaseModel,MVPBaseModel是所有Model的顶级父类,负责对外提供数据请求标准,对内为所有Model提供请求的底层支持。

/*** @author hongri* @date 2018/9/5*/public abstract class MVPBaseModel {protected String[] mParams;/*** 设置数据请求参数** @param args 参数数组*/public MVPBaseModel setParams(String... args) {mParams = args;return this;}/**** 执行Get网络请求* @param url* @param callback*/public abstract void executeGetRequest(String url, MVPLoadDataCallback callback);/*** 执行Post网络请求** @param url* @param params* @param callback*/protected void executePostRequest(String url, Map params, MVPLoadDataCallback callback) {}
}

另外这里也定义了一个DataModelManager,是针对多有Model的管理类,把其作为入口,利用反射机制可以获得对应Model对象的引用。

/*** @author hongri* @date 2018/9/5** 统一Model管理器*/public class MVPDataModelManager {public static MVPBaseModel mvpModel;public static MVPBaseModel newInstance(String modelName) {try {mvpModel = (MVPBaseModel)Class.forName(modelName).newInstance();} catch (Exception e) {e.printStackTrace();}return mvpModel;}
}

三、MVVM框架

图片源自网络

MVVM的全称是Model(模型)--View(视图)--ViewModel(视图模型):

MVVM可以算是MVP的升级版,将 Presenter 改名为 ViewModel。关键在于View和Model的双向绑定,当View有用户输入后,ViewModel通知Model更新数据,同理Model数据更新后,ViewModel通知View更新。

MVVM的优势如下:

1、ViewModel双向绑定,一方的改变都会影响另一方,开发者不用再去手动修改UI的数据。

2、不需要findViewById也不需要butterknife,不需要拿到具体的View去设置数据绑定监听器等等,这些都可以用DataBinding完成。

3、ViewModel的双向绑定是支持生命周期检测的,不会担心页面销毁了还有回调发生,这个由lifeCycle完成。

4、不会像MVC一样导致Activity中代码量巨大,也不会像MVP一样出现大量的ViewPresenter接口。项目结构更加低耦合。

下面具体介绍下MVVM框架:

1、VM层:

这里根据MVVMActivity的布局文件activity_mvvmpattern,介绍下Data Binding:

Data Binding对使用的环境还是有一定要求的:Android Studio版本在1.3以上,gradle的版本要在1.5.0-alpha1以上。
需要在Android SDK manager中下载Android Support repository
然后在对应的Module的build.gradle中添加:

android {....dataBinding {enabled =true}
}

然后使用databinding语法 对 xml 进行数据绑定,我们将 Click事件、输出结果都绑定到VM上。

<?xml version="1.0" encoding="utf-8"?>
<layoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><data><import type="android.view.View"/><variablename="userViewModel"type="com.hongri.model.mvvm.viewmodel.MVVMDataViewModel"/><variablename="handlers"type="com.hongri.model.mvvm.view.MVVMActivity"/><variablename="data"type="String"/></data><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><Buttonandroid:id="@+id/btnMVVM"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="@{handlers.onClickLoadData}"android:text="点击请求数据"/><Buttonandroid:id="@+id/btnToast"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="@{handlers.onClickShowToastName}"android:text="点击请求数据并Toast提示"/><TextViewandroid:id="@+id/tvData"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="@{userViewModel.data}"/></LinearLayout>
</layout>

VM层具体类:这里注意具体的属性需要加@Bindable,否则绑定无效。

/*** @author zhongyao* @date 2018/9/3* ViewModel层*/public class MVVMDataViewModel extends BaseObservable implements MVVMLoadDataCallback {private MVVMDataModel model;public MVVMDataViewModel() {model = new MVVMDataModel();}/*** 必须添加@Bindable注释* @return*/@Bindablepublic String getData() {return model.mData;}public void loadUserData() {model.requestData(this);}@Overridepublic void onSuccess() {notifyPropertyChanged(BR.data);}@Overridepublic void onFailure() {}
}

2、View层(MVVMActivity)引入VM:

/*** @author hongri* View层*/
public class MVVMActivity extends AppCompatActivity {private MVVMDataViewModel userViewModel;private TextView tvData;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ActivityMvvmpatternBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_mvvmpattern);userViewModel = new MVVMDataViewModel();binding.setUserViewModel(userViewModel);binding.setHandlers(this);tvData = binding.tvData;}public void onClickShowToastName(View view) {Toast.makeText(this, tvData.getText().toString(), Toast.LENGTH_LONG).show();}public void onClickLoadData(View view) {userViewModel.loadUserData();}
}

3、Model层:

用来进行具体的数据请求操作。

/*** @author hongri* @date 2018/9/3* Model层*/public class MVVMDataModel {public String mData;public MVVMDataModel() {this.mData = "初始数据";}public void requestData(MVVMLoadDataCallback callback) {this.mData = "数据请求成功";callback.onSuccess();}
}

MVVM虽然有这些个优点,但使用起来的坑也是不少的,所以目前MVVM框架在实际开发中应用并不是很多,主要以MVP框架开发为主。

最后提供下github源码,供大家参考:

源码下载

参考:

https://github.com/googlesamples/android-architecture

深度阅读(O(∩_∩)O):

Android面试题总结(最全)

Android开发框架模式(MVC、MVP、MVVM)实例解析相关推荐

  1. Android开发框架模式MVC、MVP使用总结

    一.基础概念 Android中最常用的框架开发模式是MVC和MVP.        这里要区分设计模式和框架模式.设计模式有23种,比如单例模式,工厂模式,适配器模式等等,都是java的设计思想相关的 ...

  2. Android 开发架构-MVC MVP MVVM详解

    何为架构 架构,即程序的逻辑组织结构,是指导开发过程中划分程序逻辑模块的关键,好的架构要使程序达到高内聚低耦合的设计目标.例如一个人,身体的骨骼即为身体的架构,有了基本骨架之后,才可以决定在头颅里开发 ...

  3. 界面之下:还原真实的MV*模式 -( MVC , MVP , MVVM )

    UPDATE(2015-10-29):更新MV*关于业务逻辑的描述,此处感谢 @LuoPQ @finian 指出错误 作者:戴嘉华 转载请注明出处并保留原文链接( #11 )和作者信息. 目录: 前言 ...

  4. mvvm模式和mvc的区别_Android 开发中的架构模式 -- MVC / MVP / MVVM

    预备知识 了解 Android 基本开发 看完本文可以达到什么程度 了解如何分析一个架构模式 掌握 MVC,MVP,MVVM 架构定义和实现 更多面试内容,面试专题,flutter视频 全套,音视频从 ...

  5. Android中常见的MVC/MVP/MVVM模式

    Android中常见的MVC/MVP/MVVM模式 经典MVC 在1979年,经典MVC模式被提出. 在当时,人们一直试图将纯粹描述思维中的对象与跟计算机环境打交道的代码隔离开来,而Trygve Re ...

  6. Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    本文转载自https://www.tianmaying.com/tutorial/AndroidMVC,原文作者周鸿博. 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开 ...

  7. [Android答答答]什么是MVC/MVP/MVVM

    什么是MVC/MVP/MVVM? 概念 1.MVC是什么? 2.MVP是什么 3.MVVM是什么 原理 1.MVC的特点是什么 2.MVP的特点是什么 3.MVVM的特点是什么 概念 1.MVC是什么 ...

  8. Android架构设计之MVC/MVP/MVVM浅析

    目录 写在前面 一.案例演示 二.MVC模式 2.1.MVC简介 2.2.MVC模式的使用 2.3.MVC模式的缺点 三.MVP模式 3.1.MVP简介 3.2.MVP模式的作用 3.3.MVP模式的 ...

  9. Android 系统(77)---MVC,MVP,MVVM的区别

    MVC,MVP,MVVM的区别 一.MVC 软件可以分为三部分 1.Model:模型层,负责处理数据的加载或者存储  2. View:视图层,负责界面数据的展示,与用户进行交互  3.Controll ...

最新文章

  1. shell+中sum的用法_Shell中函数使用
  2. 在TABLE CONTROL 输入完一行记录,按回车的时候光标自动移动到下一行
  3. mssql查询所有上下级
  4. VS2019 更新MSDN并创建快捷方式
  5. python手机话费_查询话费订单详情示例代码
  6. Java 面向对象 之 接口 火车票实例
  7. Java基础篇:什么是线程优先级?
  8. 虚拟机中centos7 安装过程中没有自动获取到网络
  9. freemarker 如何获得list的索引值
  10. SPSS22.0简体中文破解版(32位/64位)使用方法
  11. 商城系统演示站 -多用户商城系统
  12. TS助手 v3.52 视频网站下载工具,网页视频下载神器
  13. webqq机器人java_一步一步来做WebQQ机器人-(二)(第一次登陆)
  14. Spring Data ElasticSearch - 分布式搜索和数据分析引擎 相关操作实战流程
  15. linpack测试软件,服务器性能测试(linpack,stream,netperf,iometer)
  16. java 排班日历_快速简化排班(智能排班)-日历排班
  17. 计算机网络基础之计算机网络
  18. GBase 8s 客户端工具之dbaccess
  19. 非华为电脑管家连接平板--无法连接问题解决方案之一
  20. SWF与FLV文件格式

热门文章

  1. 电视机与遥控器(友元类)
  2. 条码读码器提供更高的读取率
  3. 【大学物理·光学】单缝的夫琅禾费衍射
  4. Foxit_PDF_SDK.NET.7.X优化插件XFA的改进
  5. cia402 状态字_解析CiA402.doc
  6. Swift中string转换float/double的若干方法
  7. 动态规划——数字三角形C语言
  8. 小五思科技术学习笔记之EIGRP
  9. android 脱壳工具
  10. C语言 宏定义练习:计算平方