背景:最近在学Android,老师介绍了一个对于我们来说是新的开发模式。mvp模式,说实话一开始我是抵制的,尽管我认为mvc模式已经做的足够好了,但是不管是mvc还是mvp都是要看其背后的环境而定的。
来,说重点!!!在我们平常的开发时候经常会用到mvc模式,包括我的前两篇文章中项目的目录结构也是严格按照mvc的模式来做的。但是这仅限于我们平常在非android环境下开发。
非安卓环境下开发的模式图:
经常使用Spring框架或者SM框架SSM框架开发的朋友对这个基本的业务流程图应该特别熟悉吧,这张图想表达的意思就是,我们不要为了一个学一个新模式而去学一个新模式,上面这张图就是咱们普通的web项目的流程图,不管其中的实现原理如何,此时的mvc与mvp是没有区别的,view层都不是直接与提供数据层(mvc中叫dao层,mvp中叫model层)进行对话的,都是通过service层(mvp中叫presenter层)间接来实现的。
但是这是正常情况下,也不乏有的朋友直接在dao层(model层)就直接与view层进行交互了,这种情况在Android中尤为盛行,为什么这么说呢?
我想问大家,学习android的时候还记得一句话吗?不能在分线程中更新UI。那么分线程用来干啥?而分线程通常都是进行网络请求或者耗时操作,例如读取本地文件 ...总之就是提供数据,相当于model层(mvc中叫dao层)然后通过runOnUiThread(new Xxx)或者Handler把刚才请求的数据进行消息的(view层)的更新。想想这样是不是view -> model,model -> view呢?那我们说这是view层直接与'提供数据层'(mvp中叫model,mvc中叫dao)进行对话,这样代价是巨大,甚至中间的都没有service层(mvp中叫presenter层),所以说在android中view层干了普通JavaEE工程中两个人的活(即controller + service),所以通常我们在使用新模式之前,Acticity中的代码都非常冗长,甚至动辄几千行。啥也不说万一哪天程序不稳定让你去找bug,你上一看几千行代码,害怕不?是你写的还好,要不是呢?下面附上Android开发的流程图:
所以我们在android中也要将之改进,不得不说mvp模式的设计之巧妙,它甚至只需要view层通过一个时机去触发它,然后剩下的诸多流程甚至到最后的视图更新都会自动完成。
那么如果我们在android中也想实现如下图这样的开发模式,将Activity中的逻辑处理代码,转交给service(presenter)层我们该怎么做呢?
答案:使用mvp模式:
总体来说用一句话概括,
-1.不管是view层、presenter层、model层都去创建属于自己的接口,
-2.presenter层的接口一定要集成view层与model层的接口以便操作(也可以扩展自己的方法)。
-3.剩下的事儿就是presenter层等待被触发,一旦被触发就会执行各种操作,然后(通知model层提供数据,通知view层更新数据)。
## 来,咱们上代码。代码是一个小案例就是点击按钮下载图片,然后在本地读取图片再显示到界面上。
先看目录结构:
来上面我们说过我们要为每一层都创建接口(不是绝对视情况而定,这里为了演示),
来我们先看看view层的(MainActivity)类的接口:
先不说presenter层 ...
再来看看model层的接口:
再看看presenter层某类的接口
然后我们的工作就是一一实现他们,下面贴图:
view层MainActivity类实现 => MainActivityInterface接口
presenter层的DealPicDataPresenterImpl类实现 => DealPicDataPresenterInterface接口
model层的PicModelmpl类实现 => PicModelInterface接口
上面我们定义了三个接口又分别提供了三个实现类。下面还有 utils工具包中的GET类作为一个联网请求数据的帮助类。
...
图中的url就是资源地址,Map集合中存放的就是我们的请求头数据最后将Bitmap对象返回。
来,基本架构我们都已经搭好,接下来就是写逻辑。
在哪写起?按逻辑写:
/*
需求分析:
-1).view层点击按钮触发事件,向presenter层发起请求。
-2).presenter层的相关方法进行处理
-3).首先调用view层的showDialog显示Dialog->
再调用Get类中的方法获取Bitmap对象->
调用model层中的savePic方法保存图片->
再调用model层的getPic读取图片,->
再调用view层的settingPic设置图片 ->
再调用view层的removeDialog移除Dialog
*/
来,我们一步一步实现,
首先是view层向presenter层发起请求
然后是presenter层的DealPicDataPresenterImpl类的dealRequestData方法接收请求并处理
首先是联网请求数据之前就先设置显示Dialog。
由于下一步我们要进行联网请求资源所以我们要先声明权限
这还不够,因为在android6.0以上的手机还必须得动态的申请运行时权限,来,看代码!!!
此刻我们在presenter层中已经拿到了请求下来的图片的bitmap对象,并调用model层的savePic方法进行图片的存储。
下面我们就要从presenter层中调用model层的getPic方法读取图片
来,上代码!
model层中的getPic方法
接下来我们既然从本地中将下载好的图片读取出来了,就差设置图片与移除Dialog了。
调用view层的settingPic方法设置图片
剩下的我们就该移除Dialog了,来我们重新回到presenter层中的DealPicDataPresenterImpl类中
调用view层的removeDialog方法来移除Dialog
好啦,我们已经成功的写好我们的代码啦,让我们跑一下。
总结一下:
-1).无论是mvp模式还是mvc模式都只是一种考虑问题的方式。万万不可拘泥于固定的套路,其实如果就向上面似的写个小案例用了mvp反倒是越来越啰嗦了。
-2).在我们普通的mvc架构的web工程中是不涉及视图层与'数据提供层'(持久化层)之间的交互的,所以不会产生什么问题,当然也因人而异。只有在Android中视图层与'数据提供层'(持久化层)交互最为亲密,不该出现在(视图层)例如Activity的代码越来越多。
-3).在Android中mvp模式的应用的核心就是只需要视图层的一个请求,presenter层就会驱动相关的组件进行交互与运转,视图层不会直接与model层进行交互,因为是presenter层驱动所以presenter层就充当了view层与model层之间的桥梁。
-4).presenter层是怎么驱动其它两层的呢?就是通过接口定义的规范。
-5).对于持久化层来说mvc模式对应的是(dao层),mvp模式对应的是(model层)。mvc是(controller、service、dao),MVP是(view、presenter、model)。