加入收藏 | 设为首页 | 会员中心 | 我要投稿 衡阳站长网 (https://www.0734zz.cn/)- 数据集成、设备管理、备份、数据加密、智能搜索!
当前位置: 首页 > 站长资讯 > 评论 > 正文

关于MVC/MVP/MVVM的一些错误认识

发布时间:2019-11-04 19:08:44 所属栏目:评论 来源:科技在发展
导读:在Android开发中使用MVP和MVVM模式早已不是新鲜事了,各种MVP/MVVM相关的文章、开源库也已屡见不鲜,甚至是让人眼花撩乱,那么我为什么还要在这个早已被画满涂鸦的黑板上再来涂涂画画呢?是想彰显我的存在感吗?那当然!啊不不不不完全是!我还想要警醒读到这
副标题[/!--empirenews.page--]

在Android开发中使用MVP和MVVM模式早已不是新鲜事了,各种MVP/MVVM相关的文章、开源库也已屡见不鲜,甚至是让人眼花撩乱,那么我为什么还要在这个早已被画满涂鸦的黑板上再来涂涂画画呢?是想彰显我的存在感吗?那当然!啊不不不……不完全是!我还想要警醒读到这篇文章的各位:你们对于MVX的理解可能并不完全正确!

注:这篇文章里我将使用 MVX 做为MVC、MVP以及MVVM的统称。

我们都知道MVX的进化过程是从滚球兽进化到MVC,然后从MVC进化到MVP,再从MVP超进化到MVVM。那么接下来,按照常规的套路,我应该要介绍什么是MVC,什么是MVP,以及什么是MVVM,并且分别介绍M、V、C/P/VM各自的职责了。

关于MVC/MVP/MVVM的一些错误认识

我的目的是想要纠正一些对MVX的错误认识,所以前提是你要对MVX有一些了解。为了避免有人在使用MVX时走上弯路,所以决定对我看到的一些关于MVX的错误认识进行总结以及纠正。会产生这些错误认知的原因,经我分析,其实是:没有真正领会到MVX主义的核心价值观!其实MVX的核心思想也很简单,不要误会,不是富强、民主、……而是 将表现层和业务层分离 。

表现层和业务层分离

表现层和业务层分离,Matin Fowler称之为Separated Presentation。这里的表现层就是VX,业务层就是M。如果有人看到这里发现了和你认为的MVX不一样的话,那么你对MVX的认识很可能就存在错误,严重者还可能是走了修正主义路线!

从表现层和业务层分离的视角来看,M、V、X不是平等的身份,应该是M和V-X。自始自终M的职责都没变,变的是V-X,随着软件开发技术的发展、交互形式或者交互媒介的不断改变,表现层的逻辑也越来复杂,MVX的进化过程就是一个不断探寻处理表现层复杂逻辑的过程。当然从一个形态进化到另一个形态,并不一定是为了解决更复杂的交互逻辑,也可能是有了一种“更优雅”的方式来处理表现层逻辑。

既然已经有表现层和业务层分离的概念了,那么第一个错误观点就很好解释了。

错误一:Presenter或者ViewModel负责处理业务逻辑

这是一个很常见的错误观点,很多介绍MVP或者MVVM的文章都这么说过。正如前面所说,业务逻辑是属于M层的,那Presenter或者ViewModel是干什么的,处理表现层逻辑的吗?是的,或者说大部分表现层逻辑都是在Presenter或者ViewModel中处理的。之前我将业务层之上的这些逻辑称之为视图逻辑,现在为了统一就叫做表现层逻辑吧(加个吧字怎么感觉怪怪的)。

我在这里就简单说一下什么是表现层逻辑,以及View和Presenter/ViewModel又是如何分工的。假设你的应用有一个个人资料的profile页面,这个页面有两种状态,一种是浏览状态,一种是编辑状态,通过一个编辑按钮触发状态的转换,编辑状态时,部分信息项可以进行编辑。那这里就有一个明显的表现层逻辑,那就是点击按钮切换浏览/编辑状态。

现在的MVP的流行形态(或者变种)叫做Passive View,它和MVVM一样现在都倾向于将几乎所有的表现层逻辑交给Presenter或者ViewModel处理,View层需要做的事情很少,基本上就是接受用户事件,然后将用户事件传递给Presenter或者ViewModel。以上面的profile页面的例子来解释的话就是,View层负责接收编辑按钮的点击事件,然后通知Presenter/ViewModel,然后Presenter/ViewModel通知View是显示浏览状态的视图还是编辑状态的视图。MVP的示例代码大概是这样的:

  1. public class ProfileView { 
  2.     void initView() { 
  3.         // 负责注册点击事件监听器,并将点击事件通知给presenter 
  4.         editStateButton.setOnClickListener(new OnClickListener() { 
  5.             presenter.onEditStateButtonClicked(); 
  6.         }) 
  7.         ... 
  8.     } 
  9.  // 显示浏览状态视图,想不到好名字,就叫showNormalState吧 
  10.     public void showNormalState() { 
  11.         // 浏览状态下编辑按钮提示文字为“编辑”,所有项不可编辑 
  12.         editStateButton.setText("编辑"); 
  13.         nickName.setEditable(false); 
  14.         ... 
  15.     } 
  16.     public void showEditState() { 
  17.         // 浏览状态下编辑按钮提示文字为“完成”,部分项要设置为可编辑 
  18.         editStateButton.setText("完成"); 
  19.         nickName.setEditable(true); 
  20.         ... 
  21.     } 
  22.  
  23.  
  24. public class ProfilePresenter { 
  25.     private State curState = State.NORMAL; 
  26.     public void onEditStateButtonClicked() { 
  27.         // 按钮被点击时,根据当前状态判断View应该切换显示的状态 
  28.         // 这就是表现层逻辑 
  29.         if (isInEditState()) { 
  30.             curState = State.NORMAL; 
  31.             view.showNormalState(); 
  32.         } else { 
  33.             curState = State.EDIT; 
  34.             view.showEditState(); 
  35.         } 
  36.     } 
  37.     private boolean isInEditState() { 
  38.         return curState == State.EDIT; 
  39.     } 
  40.     @VisibleForTest 
  41.     void setState(State state) { 
  42.         curState = state; 
  43.     } 

注:这个示例代码只是为了展示表现层逻辑,没有涉及到Model层,编译也不会通过的!

(编辑:衡阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读