Android的MVC,MVP模式

我的想法

古今中外,无论是习武还是格斗,都有一套自己的招式。但是实战中,没有人傻乎乎的按书本上原封不动的施展招式,实战才能得到更好的变通,这篇文章记录我在安卓实战过程中对MVC模式,MVP模式的理解。

我对MVC的理解

我在自己人生的第一个android项目中用了MVC模式,其实说是使用了MVC模式,不如说是MVC模式使用了我。因为入门的书籍只会教你怎么用,而不会教你怎么用好。

图1在安卓开发中,MVC模式的使用多是以上图形式出现的。

C是整个模式的核心,C即Controller(控制器),负责调度,实际上C多由Activity承担,他与View的关系在于,当在Activity中调用setContentView之后,整个View被测量,布局,绘制,当执行完onStart后,根View就被添加到window中,也就是说,Activity持有整个树状布局的引用,可以得到View树上的任何一个View。Activity可以控制View的初始化,数据填充,以及在新数据到来时更新View;他与Model的关系在于,Activity可以向网络进行请求(HTTP),也可以向SQL,CACHE请求以获得自己需要的数据。

V即View(视图),V与C的关系在于,View是人机交互的接口,人在View上的部分事件处理可以交给C处理逻辑,比如对按钮的点击处理就可以放在Activity中setViewOnClickListener来编写逻辑。V与M的关系在于,一些View可以不通过C来编写逻辑而自我的向Model请求数据,从而完成自己的初始化或者更新。
用虚线表示是因为这个MVC模式中View破坏封装的错误操作,但Android事件分发的特性又使得这样的避免很难。为什么说他难,正如“按钮的点击处理可以通过在Activity中用setViewOnClickListener来编写逻辑”,这时间是就是一个回调,当按钮点击时,回调我们传进去的listener的逻辑。那么对于每一个需要与Model层请求数据的View而言,他都要去实现这样一个回调的接口,以保证所有的请求都由C来完成。然而,这样很容易破坏原本的事件分发特性,事件分发简单说是从上到下,每遇到ViewGroup判断是否拦截,否的话继续向下分发,直到一个View或ViewGroup通过onTouchEvent响应了这个事件。那么试想我们每一个按钮都通过setViewOnClickListener在Activity中回调,那么我们就可以在按钮的listener逻辑中相互处理事件,而不受事件分发特性的监管。这无疑是非常恐怖的。所以上面提到的“虚线表示的MVC模式中View破坏封装的错误操作”只是为了避免事件泄露更加错误的操作。

2019年10月16日 删除上面的内容,是发现我当时钻入了安卓事件分发的特性当中不能自拔,什么问题都想向事件分发靠拢,结果说了很多错误的话。

V即View(视图),MVC模式中的View其实也与Android中的View相对应,在View当中,我们可以绕过Activity与Model层交互,同时View也在进行人机交互的任务。

M即Model层,用于封装请求。与C通过callback返回请求到的数据。

如果上面的话是一本武林秘籍,那么读完之后可能会觉得,除了虚线带来的弊端,MVC模式也可以充分解耦,但事实真的是这样吗?

实际上,C层多由Activity承担,但Activity和View的关系密不可分,View的测量,布局,绘制,持有View的引用,编写View的listener的逻辑等等。。。Activity不仅要处理对Model层数据的请求、Model层返回的数据,还要处理View层的显示,以及View事件的处理。这就会造成,最终我们的Activity代码非常臃肿,难以维护。复杂的调用关系以及频繁的数据请求与处理,会让我们迷失在Activity的维护中。我现在甚至不想多看一眼我第一次安卓开发时的Activity代码,如果你想看,给你个链接去看吧。是一个关于食堂点餐的开发。
https://github.com/Lostcanteen/Delicious_canteen

我对MVP模式的理解

小插曲

在我完成自己人生第一次安卓开发(就是上面github里的app)的半年之后,我有幸去了BAT之一实习,并顺利的拿到了offer,虽然最后拒了他们的offer回学校上大四,准备读研究生,同时我也没放弃安卓开发。迷茫是20岁应该的,我想在我不确定自己未来路的时候,多试试也不会太错。

正题

人是要进步的,有了在公司的一点点积累后,我在自己回学校的第一个安卓开发项目中,决定摒弃之前臃肿的MVC模式,转用MVP模式。
在这里插入图片描述
更新:其实MVP的核心在于将整个逻辑与显示、请求分开。在MVC模式当中,Android的View,Activity不仅承担着逻辑代码,也承担着显示、请求等任务,那么当所有任务集中的时候,出现错误是难排查的,交付给其他人的时候代码也是难阅读的。解耦才是MVP相较于MVC的核心。

P是MVP模式的核心,即Presenter,他与Android中的任何组件都没有关系。他和View相互持有引用,View向P发送Action,P根据Action处理相应的逻辑,P通过View的引用来通知更新View。此时我们应该注意,Activity和View一样,被当做V来处理,这样我们可以在P中处理复杂逻辑和相互调用,在V中仅负责向P发送Action、更新UI,职责更明晰。
实际上,P和V都应该用接口实现,使得对应的V和P彼此暴露的方法尽可能的少,以此来减少破坏封装的调用。

MVP模式解决了上述不可避免的虚线问题,我们的P和V是一一对应的,所以当V创建后,P也是一个树状结构。任意一个V决定处理事件后,就可以向它的P发送Action->P请求数据->P更新V,V在将事件处理完毕向上传递。而在MVC中,C和V是多对一的,且C并不是树状结构的。

后语

其实我最后的MVP模式,将M层全部封装在了一个Service中,如图
在这里插入图片描述

IPresenter

  • void onCreate(Bundle bundle)
  • void onStart()
  • void onStop()
  • void onDestroy

IView

  • void setPresenter(IPresenter presenter)
  • IPresenter getPresenter()

所有的P都继承自IPresenter,所有的V都继承自IView。

发布了11 篇原创文章 · 获赞 21 · 访问量 9245

猜你喜欢

转载自blog.csdn.net/BigPig_LittleTail/article/details/84441597