对于程序框架的选择,由于android天然的MVC,本来不需要另外设计直接使用即可。但是我更加钟情于MVP模式,对于其将ui完全与业务逻辑分离的思路很赞同。

那么什么是业务逻辑?个人认为,对数据(即MVC中的M)的处理即为业务逻辑,数据主要有3个来源:

  • 服务端返回的数据
  • 从其它途径传入的数据
  • 自己定义的数据(需要传递时)。

实际操作中,指不定哪天老板说,啊这个页面颜色太淡了,这个页面按钮太多了,另一个页面文字换成图片。

怎么办?美术负责人说,我做两个版本吧,先上线测试,看看哪个效果好就用哪个。

你该怎么做?

  • 反驳老板,说他是错的,然后第二天你就可以去找一份新工作了。本文到此结束。
  • 不反驳老板,往下看。

既然选择忍辱负重,那么就要努力想解决方案。

如果使用MVC模式,你需要复制你的Activity,建立新的文件 Activity2,然后删除页面相关代码,添加新的页面代码。

这样做可以完成任务,但是有2方面的问题:

  • 修改页面时,其中混杂的业务逻辑就会从中作梗,因为某些业务逻辑会跟view操作写在同一个函数中。因此在修改view的时候,很容易就修改/删除了某些业务逻辑相关代码。这样,等你写完了之后恐怕连你自己都没法保证没有写错。后续就是大量的测试和代码对比。如果明天老板就要验收,或者让你改第三次怎么办?
  • 业务逻辑冗余,你会发现两个activity中有着大量相同的代码。一旦某个业务逻辑需要改变,比如接口名称变化,你需要修改两个地方。

这时候你可能会想,我把业务逻辑封装成一个个函数,给这些函数添加适当的参数和返回值,然后提取到另一个类中,比如就叫做ActivityDataHandler。来表示Activity业务逻辑的处理。

这样问题不就解决了吗!

  • 首先业务逻辑不会跟页面混杂,只要看到ActivityDataHandler的实例就知道是业务逻辑了。
  • 其次不会有2处业务逻辑了。因为都封装到ActivityDataHandler中了。

但是问题又来了,如果说对数据的修改仅仅是来自页面操作,上面这样做是可以解决问题的。

如果数据的修改不是通过页面操作进行的呢?比如某个接口调用之后,数据理应传给ActivityDataHandler,而不是Activity。

Activity怎么才能知道数据回来了,进而刷新页面?

这时候你明白了,需要在ActivityDataHandler中添加一个引用,指向Activity,这样每次ActivityDataHandler中的数据变化都可以直接调用activity中的方法了。

嗯不错,问题似乎解决了。但是你还是忽略了一个问题,那就是Activity不止一个。

在这种情况下你需要在ActivityDataHandler中添加多个Activity的引用,然后在数据变化时,用if-else来判断调用不同activity的不同方法。

这样上面的问题是解决了,但是又引入了新的问题。ActivityDataHandler中添加多个Activity的引用,这本身就是一个冗余,从设计模式角度来讲,如果一个两个还好说,如果需要添加10000个则需要修改ActivityDataHandler10000次,这违反了设计模式中的:开闭原则。

所以这时候你会想,我把Activity中涉及因为数据的改变而需要修改页面组件的部分,封装成不同的方法,然后把这些不同的方法提取到一个接口中,IActivity。这样每次新加入一个Activity只需要继承IActivity,然后把IActivity的引用传给ActivityDataHandler即可。

这样ActivityDataHandler只需要引用一个IActivity就够了,不用关心具体是哪个activity,这体现了设计模式中的依赖倒转原则:只针对接口来编程。
嗯,这时候你舒了一口气,说,这下没问题了吧!哈哈,确实,表面上看似乎没问题,很完美。

但是别高兴的太早,因为此时老板和美术人员可能不找你麻烦了。但是后端程序和产品经理又向你走来。

后端程序说,我这个接口不太稳定,因为网页端需要测试,所以可能某个页面要写2套接口,你这边最好兼容一下,我给你个参数,你用这个参数来判断调用哪套接口。。

产品经理说,这个页面跳转回来后,我不确定应该显示什么内容,到时候要具体根据统计数据来看,所以我希望,一部分用户跳转回来后显示真数据,另一部分用户则显示假数据。。

这时候你说,没问题,我在接口调用的地方加一个if-else来判断调哪个接口。然后,在页面跳转后数据修改这里也加一个if-else,判断这个用户类型,然后给返回不同的数据。

然后你犹豫了一下,觉得似乎哪里不对劲。回头看了看上面Activity修改时所遇到的问题,于是明白了问题所在:违反开闭原则。

找到问题就简单了,解决方法同上面解决多个Activity引用的方法一致:建立IActivityDataHandler,为不同的逻辑添加多个ActivityDataHandler。然后Activity中添加IActivityDataHandler引用。

问题至此完美解决。

Activity,IActivity,ActivityDataHandler,IActivityDataHandler。这四个类及上述分析,就构成了MVP模式。

如此看来,MVP确实是个不错的框架,解决了不少问题,但是在我看来,它实践起来还是有一定的困难的。

MVP其实就是把MVC中的C再次拆分为V和P的一个框架。

主要问题有3个:

  1. 做功能的程序员每写一个activity需要写多个文件一个Activity,一个Presenter,一个IActivity的接口,一个IPresenter的接口,麻烦,对于一个快速迭代的项目(已知不会有太多的变化和修改)来说不是很轻便。而且文件一多,有些思维不连贯的程序员就会混乱。
  2. Activity和Presenter任务不明确,有时需要2个类同时处理的某些操作,会令程序员造成迷惑。
  3. Activity和Presenter相互引用,耦合很重。其实这一点是难以避免的。

后续会介绍我是如何搭建具有个人特色的MVP模式。

仅需6步,教你轻易撕掉app开发框架的神秘面纱(2):MVP比MVC更好吗相关推荐

  1. 仅需6步,教你轻易撕掉app开发框架的神秘面纱(1):确定框架方案

    遇到的问题   做游戏的时候用的是cocos2dx+lua,游戏开发自有它的一套框架机制.而现在公司主要项目要做android和iOS应用.本文主要介绍如何搭建简单易用的App框架. 如何解决   对 ...

  2. 仅需6步,教你轻易撕掉app开发框架的神秘面纱(5):数据持久化

    遇到的问题 有的时候程序中需要全局皆可访问的变量,比如:用户是否登录,用户个人信息(用户名,地区,生日),或者一些其他信息如:是否是首次登录,是否需要显示新手引导等等. 其中有些数据需要持久化到本地硬 ...

  3. 仅需6步,教你轻易撕掉app开发框架的神秘面纱(4):网络模块的封装

    程序框架确定了,还需要封装网络模块. 一个丰富多彩的APP少不了网络资源的支持,毕竟用户数据要存储,用户之间也要交互,用户行为要统计等等. 使用开源框架 俗话说得好,轮子多了路好走,我们不需要自己造轮 ...

  4. 仅需6步,教你轻易撕掉app开发框架的神秘面纱(3):构造具有个人特色的MVP模式

    1. MVP的问题 之前我们说过MVP模式最大的问题在于:每写一个Activity/Fragment需要写4个对应的文件,对于一个简易的app框架来说太麻烦了.所以我们需要对MVP进行一定的简化. 关 ...

  5. 仅需6步,教你轻易撕掉app开发框架的神秘面纱(6):各种公共方法及工具类的封装

    为什么要封装公共方法 封装公共方法有2方面的原因: 一是功能方面的原因:有些方法很多地方都会用,而且它输入输出明确,并且跟业务逻辑无关.比如检查用户是否登录,检查某串数字是否为合法的手机号.像这种方法 ...

  6. 怎么快速修改gif尺寸?仅需三步教你改gif大小

    很多时候我们从网上下载的gif动图或者是从电影.电视剧中截取的高清gif动图尺寸过大不方便传输,想要对gif图片尺寸修改的时候应该如何调整gif尺寸呢?很简单,使用[GIF中文网]的gif改大小(ht ...

  7. python爬虫excel数据_最简单的爬数据方法:Excel爬取数据,仅需6步

    原标题:最简单的爬数据方法:Excel爬取数据,仅需6步 在看到这篇文章的时候,大家是不是都还停留在对python爬虫的迷恋中,今天就来教大家怎样使用微软的Excel爬取一个网页的后台数据,注:此方法 ...

  8. 隐藏esp_仅需一分钟教你看懂汽车内的隐藏功能,哪些功能是你不知道的?

    车内的按键多种多样,而且越高档的车,按键就越多.除了少数国产车,绝大部分车辆的按键标识都是用英文字母表示,从而导致不少车主只能通过查看说明书才知道是什么意思. 今天小编整理了车内各种按键标识,不是很清 ...

  9. php 商城套餐搭配功能,速卖通商品搭配套餐功能已上线!设置速卖通搭配套餐仅需三步...

    据雨果网获悉,速卖通商品搭配套餐功能已于 10 月 19 日上线.商品搭配套餐的主要功能及作用,主要是帮助速卖通的卖家,通过自行选择商品,设置不同商品间搭配优惠促销价格,提高商品推广内容的丰富性及专业 ...

最新文章

  1. 在测试者的易用性测试工具套装中他们需要什么(译)
  2. 快速理解Spark Dataset
  3. out参数不用赋值?这么神奇吗!
  4. 前端学习(1395):多人管理项目15建立请求
  5. java中 若干,Java中的随机数发生器。产生若干的复杂性
  6. MAC系统下解决Teamviewers检测出商业限时问题
  7. 判断系统大小端方法分析与总结
  8. 查看特定进程杀死进程方法
  9. Bitfinex将向纽约总检察长办公室移交“被指控 8.5 亿美元资金挪用案”相关文件
  10. 保存单文件为mhtml
  11. 已知空间三点求圆心c语言,空间三点计算圆心坐标和半径
  12. 大型网页游戏开发流程
  13. laravel框架使用datatables
  14. vue下载文件流图片
  15. 浅谈 | 从Web安全到APT防御
  16. python实现fastq文件GC含量的计算
  17. 一款灵活可配置的开源监控平台
  18. mac电脑usb连接android手机,Android安卓设备连接Mac的方法
  19. Android studio gradle编译失败问题汇总
  20. VBA解析json示例1

热门文章

  1. 学术-数学:哥德巴赫猜想
  2. WC2018集训 吉老师的军训练
  3. 10-TypeScript中的接口
  4. js 跨页面的全局变量
  5. cf776G.Sherlock and the Encrypted Data
  6. GridView的编辑,更新,取消,删除等功能演示
  7. Web 开发与设计之 Google 兵器谱
  8. 网页中如何获取客户端系统已安装的所有字体?
  9. ATL::CStringA和std::string之间转换的一些误区
  10. Linux下通过gettimeofday函数获取程序段执行时间