Android MVP 架构设计之美

强烈推荐我的Android视频实战课程

从零打造一款跟随灵魂的高性能社交App

我们经常在讨论Android的架构,MVC,MVP,或者MVVM,有些同学觉得架构好App就做得好,其实这是错误的,我们归根结底还是需要找到自己合适的架构,适合自己的才是最好的,所以如何选择适合自己的架构才是关键。

 

《银河补习班》中有一句话:人生就像射箭,梦想就像箭靶子,如果连箭靶子也找不到的话,你每天拉弓有什么意义?”

              

你得先了解你的需求,你的功能,你的可扩展方向,你才能知道,哪个架构适合你,同样你也要了解这些架构的优点,缺点,以及痛点,MVC能用这么久必然有它的道理,很多人舍弃MVC转而去使用MVP也必然有它的道理,既然里面这么多问题,这么多道道,我们想深度的了解,那么就需要刨根问底了。

一.简介

先来说说MVC吧,分解出来,就是Model,ViewController对吧,再转换一下就是模型视图控制器了,Model我们可以不用理会,主要来看下视图和控制器,控制器我们可以换一种说法,也就是逻辑,那么可以总结出:MVC就是视图与逻辑分离,再精简一下,View就是我们的XML,而逻辑就是我们的Activity或者Fragment等类,这样就好理解了吧,他们的分工是明确的,布局就负责UI,Activity就负责逻辑。

 

这套架构沿用了几十年,也深受各界的爱戴,然而随着互联网乃至IT界的高度发展,需求越来越多,代码越来越多,项目也越来越大的情况下,你会发现,哪怕你写得代码再美,再精简,各种管理类,帮助类,特别是Activity,异常的臃肿,几千行都不叫事儿,我上万行的都见过..... ,而且你会发现一个问题,虽然架构叫MVC,但是View其实能做的工作特别少,各种控件的赋值,操作都是在Activity中完成的,倒不如干脆叫MC构架?(大家好,我是MC喜洋洋,青青草原我最狂~)

 

这个时候工程师们就意识到了,必须去做一些改变了,将逻辑层进行解耦,所以我现在回头看看MVP,你就明白他是干什么的了。

 

那么我们说到MVP,首先依旧是分解它,Model,View,以及Presenter ,你会发现,与MVC来讲,一个是C一个是P,也就是,模型视图接口层,P的职责就是连接View和Model并且对业务逻辑进行处理,相当于一个中转,Model将数据处理好之后通过Presenter传递给View去更新UI。

 

按照百度百科的说法:MVP是从经典的模式MVC演变而来,它们的基本思想有相通的地方 :Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。

二.图解

 

所以按照我们正常的开发思维,MVC就如图中所示:

 

             

 

当Model的值更改,则需要通过Controller去通知View修改,因为View是依附在Activity中,如果View发生更改,同样的会更改Activity的监听去修改Model的值,同样的,View中是持有Model的引用的,Model中也有View的引用控制,这样的话,显而易见,他们互相是可以调用的,首先不说这个架构是不是比较乱,单从互相引用来看,过程中的问题肯定会出现很多。

 

那么再来看下MVP,既然说MVP是MVC的变种,那么他是如何修复这种弊端的呢?我们来看下图片:

 

             

 

比较明显的两个不同点,首先是Controller替换成了Presenter,而Model与View则无法通信,所以一般其他道友总结会这样去画图:

 

             

 

所以MVP首当其冲的就是Model与View的解耦,其次就是Activity的解耦了,P作为桥梁去平摊Activity的逻辑,让Activity做到真真正正认认真真的只负责View视图显示,这个怎么理解呢?首先P持有M这个没问题吧,那么现在P需不需要持有View,也就是P与Activity的通信如何去通信,这里则需要使用到接口了,也就是ActivityInterface,P与V之间通过接口进行通信就很好的实现了他们之间的解耦了,而ActivityInterface是一个新名词,所以我们重新来梳理一下他们关系,这也是很多人学MVP搞不懂的地方,关于MVP的角色关系。

 

  • View 视图 可以理解为Activity/Fragment

  • ActivityInterface 视图接口,便于View与Presenter之间的交互

  • Presenter 作为View与Model之间的通信桥梁

  • Model 数据层

所以,注意呀,MVP会多一个接口角色,当然,有些人会给Model也写一些接口来解耦,这也是可以的。

 

那么长篇文字的赘述下,你是否有一些理解他们之间的区别了呢?不了解也没关系,现在还没到让你总结他们的优缺点以及对比的时候,现在开始进入实战吧,我们通过代码来理清楚这些逻辑岂不是印象更深刻?

 

“清华北大只是过程,不是目的”。面对儿子的长大后想干什么的回答,马皓文想让他知道,能读清华北大的人毕竟是少数,即使没有考上清华北大,人生也要有追求的目标,毫无目标的生活,就如没有箭靶子一样,每天拉弓就没有意义。

             

三.示例

同样的,MVP也并不是什么新技术,更多的是思考以及开发思路的转变,我们来做一个很简单很简单的例子吧。

 

需求:通过OkHttp请求一个Url,通过Gson转换数据,Glide显示图片,RecyclerView显示数据

 

那么我们先来看下传统的MVC写法是如何实现的:

 

先说思路吧:先创建一个实体Bean,再创建一个Adapter,然后在Activity中初始化RecyclerView后,通过OkHttp请求数据后,填充到Adapter中,所以我们先看下实体类

 

             

 

我们只需要取ResultBean中的几个数据即可,再来看下Adapter

 

             

 

在适配器中,其实没什么特别,在onBindViewHolder中填充Bean的数据就是了,然后再来看下Activity的代码:

 

             

 

这是一份很简单的代码,人人都会,那么从中你可以看出MVC相关相关的逻辑吗?首先Model就是MvpRecyclerBean,这可以理解吧,然后就是View了,View的话你可以理解为布局,再看Controller,实际上在MVC的体系中他就相当于我们这个Demo中的MainActivity了,你可以发现,他们的关系就是相互的穿插。

 

             

 

通过这张图就可以反映出来。

 

我们也可以看下效果:

 

             

 

那么我们现在通过Mvp来进行优化,是如何去做的呢?

 

其实代码本身很简单,更多的是将传统的MVC思路给转换,架构体现的就是思想,我也尽量的通过语言来一直解释其中缘由,如果只是抛出代码,实际上没多少东西,但是你学完你也会发现,也没学到多少东西,所以吾日三省吾身,思路,思想,思考

 

MVP的核心就是将UI逻辑抽象成View接口,将业务逻辑抽象成P的接口来体现,我们来看下这张图:

             

View通过接口向P获取数据,实际上P是向M获取数据,M获取到数据之后通过接口给P,P来处理后,告知View的UI逻辑。

 

你会发现,M和V是无法直接接触的,他们中间有P作为中转,很好的做到了各自的职责,那么我们来看下代码怎么改吧:

 

先来看下我创建的包名:

             

 

我们可以看到,我创建了model包下的两个类,分别是MainModel的实现以及IMainModel的接口实现,还有MainPresent的中转实现以及IMainView的UI视图实现。

 

再来看一张图:

             

 

这是MVP的核心思想,一定要仔细看,先说逻辑再说代码,首先,在MainActivity中会去创建MainPresent的实例,这样就可以调用MainPresent的loadData方法加载数据了,在MainPresent的loadData中实际上是创建了MainModel,通过MainModel来调用他的loadData加载数据,然后MainModel作为一个执行者去通过OkHttp拉取到数据之后通过IMainModel接口的OnResultListener返回给MainPresent,MainPresent又通过IMainView的showRecyclerview接口返回给MainActivity,然后MainActivity即更新UI即可。这逻辑多读几遍,然后来看代码:

 

第一步:在MainActivity中会去创建MainPresent的实例,这样就可以调用MainPresent的loadData方法加载数据了

 

             

 

第二步:在MainPresent的loadData中实际上是创建了MainModel,通过MainModel来调用他的loadData加载数据

 

             

 

第三步:MainModel作为一个执行者去通过OkHttp拉取到数据

 

             

 

第四步:之后通过IMainModel接口的OnResultListener返回给MainPresent

 

             

第五步:MainPresent又通过IMainView的showRecyclerview接口返回给MainActivity

 

             

第六步:然后MainActivity即更新UI即可

 

             

 

前后呼应,我已经把功能和代码完全解析了一遍,你只要认真读,学会不成问题,那么你现在可以发现,我们一共创建了四个类,要是加上MainActivity就五个类了,MainActivty全部通过Present去操作逻辑,而数据层则是通过P绑定的Model层来做的,这样你是不是有一种豁然开朗的感觉,没错,结合我们之前画的图,你理解就更加透彻了。

 

当然,如果你想增加更多的接口,比如showLoding,或者showErrorDialog什么的也是没问题的,在IMainView中增加即可,然后在Present中实现就好了。

 

写完这些代码之后你会不会产生疑惑,使用MVC我只要把OkHttp请求数据的代码块直接放在Activity,然后得到结果显示就好了,但是用了MVP你却让我这个转那个转这个的,这就涉及到了MVC和MVP的优缺点了

 

  • 1.MVC和MVP都有自己的优势和劣势

  • 2.小项目优先MVC,大项目优先MVP

  • 3.MCV会让Activity十分的庞大,代码难懂

  • 4.MVP可以分解单一职责,代码易懂,却增加了很多的类和接口

  • 5.MVP高度解耦

接下来还有最后一个问题,关于内存泄漏的问题。

四.内存

关于内存,我在之前的内存泄漏中告诉过大家如何去解决此类问题,这里就不一一赘述了,我们直奔主题吧。

 

Android 性能优化之内存泄漏使用MAT&LeakCanary解决问题

https://articles.zsxq.com/id_sxewv43tsi0g.html

 

MVP的优点很多,得益于P的思路转变,但是由于P是持有View和Model的引用,那么如果View,也就是Activity退出没有及时销毁,而P或者M都有可能在异步执行,这个时候内存肯定会出现泄漏乃至溢出的风险,那解决的办法也很简单,当Activity销毁的时候也销毁P就好了,但是V这么多,都得去写P吗?这就需要去封装一个BaseP了

 

             

 

可以看到,我在这里定义了一个P的基类软引用来处理V,然后需要我们的MainPresent继承它

 

             

 

这些没什么问题,关键还是在BaseActivity中的思路

 

             

 

可以看到这边抽取之后可以得到一个Present的对象,并且通过createPresenter让外部可以实现,其他的则绑定了他的生命周期,这样就很好的避免了内存的问题了。

 

而在Activity中我只要继承了BaseActivity即可

 

             

 

可以看到,现在我依旧可以通过BaseP中的mPresenter对象来进行loadData。

 

到此,MVP就讲解完了,实际上,从始至终,我都是想让你摆脱代码的束缚,掌握这种思想,代码只是一个实现过程。

 

有兴趣的可以加入交流群:417046685

 

源码及PPT:

https://pan.baidu.com/s/1vWT-uTh_OvdgFppy58fXQQ

密码:gfk9

推荐阅读:

从零打造一款跟随灵魂的高性能社交App

也可点击阅读原文查看我的新课程。

扫描二维码

加入知识星球

Hi Android

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值