移动APP开发技术1.1基本的架构设计模式提高生产力,是对程序员们对程序进行孜孜不倦架构设计的原因。通过不同的架构设计使程序模块化解耦以及程序内部的高聚合,使得开发人员可以在开发工程中只需关注一点或者某块的功能设计而不必关注全貌,甚至以点窥面,从某个模块的理解即可覆盖全局。同时测试设计也会因为一个更良好的架构设计而改观。在本章,笔者主要针对移动端常用的MVC、MVP、MVVM三种设计模式进行比较探讨,并结合实例,来说明三者之间的差异。1.1.1MVC/MVP/MVVMMVC/MVP/MVVM是一种架构模式,它描述的是数据流向,这三者之间的差别可以由如下图,可以看到三者之前的相同点是,View均为UI层,是用户直接的交互操作入口,并负责UI交互和界面展现相关逻辑。Model层为数据对象,提供对应用程序数据的操作接口,并在数据发生变化时,发出变更通知。图1架构模式那么,它们的不同点是什么呢,在MVC中,controller被动接收View的操作事件,根据事件的不同进行不同的操作,model并不直接与controller交互,而是View通过观察者的方式,来直接与Model交互,在Android中,往往很难区分View和Controller,所以经常会看到好几千行的Activity,非常难维护;MVP可以理解为MVC的升级版,在笔者眼中,它是第一次使客户端分层得以充分实现的一种架构模式,它的特点是,Prensenter将View和Model完全隔离,View传递事件给Presenter,而presenter直接负责View的刷新;MVVM早期应用是windows的MFC上,而近期在2015年googleIO大会上,发布的新Androidstudio也支持了这一特性,它的基础是DATABINDING,这一特性从理想态上来说,完美的解决了UI前端与业务逻辑层的解耦问题,哪怕是MVP也不能具有这么好的特性。1.1.2MVP设计模式实现实现MVP并不复杂,但是重点是把握好,不要过度设计,MVP很容易导致本来很简单的代码需要大量的开发工作,写在前面,可以理解,架构的设计模式与产品体量有关,说一个极端的场景,当你的团队只有1个人,APP整体也只是一个前台展示+简易逻辑处理+数据存储+网络请求时,其实此时并不需要特别复杂的架构设计,而是,要用最简易便捷的方式将APP设计起来,这也遵循了产品设计之初快速产出,快速试错的目的。而当团队逐步增大、产品规模逐步提升,譬如,代码量超10W时,这时候为了团队协作、模块管理、便于测试等诉求,就不得不进行一定的架构设计或重构了。如何讲解一个MVP的例子,还是找一个比较简单的例子切入,可能并不能说明一切端设计的场景,但是可以作为读者了解MVP的切入点,假设有一个用户数据录入的APP,具备简单功能,即用户数据录入&&简单用户数据查询功能,它的界面看起来是如下这样的:图2简易APP用户界面最后的工程结构是这样的,如下图图3MVP基本结构第一步,实现数据载体BeanpublicclassUserBean{privateStringmFirstName;privateStringmLastName;publicUserBean(StringfirstName,StringlastName){this.mFirstName=firstName;this.mLastName=lastName;}publicStringgetFirstName(){returnmFirstName;}publicStringgetLastName(){returnmLastName;}}第二步,实现Model层,model其实是对数据的CURD操作的封装,如果有网络请求或其他需要异步处理的需求,这一层通过listener与上层的presenter进行通讯publicinterfaceIUserModel{Booleaninsert(intid,StringfirstName,StringlastName);Booleanupdate(intid,StringfirstName,StringlastName);voiddelete(intid);UserBeanquery(intid);voidreset();ListUserBeanqueryAll();}第三步,实现presenterpublicclassUserPresenter{privateIUserViewmUserView;privateIUserModelmUserModel;publicUserPresenter(IUserViewview){mUserView=view;mUserModel=newUserModel();}publicvoidsaveUser(intuserId,StringfirstName,StringlastName){mUserModel.insert(userId,firstName,lastName);}publicvoidloadUser(intuserId){UserBeanuser=mUserModel.query(userId);mUserView.setFirstName(user.getFirstName());mUserView.setLastName(user.getLastName());}}第四步,实现View层publicinterfaceIUserView{StringgetFristName();StringgetLastName();voidsetFirstName(StringfirstName);voidsetLastName(StringlastName);}其中,没有标准Activity和model的实现,相信读者可以参考IUserView和IUserModel的接口就可以实现对应的view层和model层实体了。这样就算是基于MVP设计模式,设计了一个简单的APP。但是这个APP的实现是不全的,但是对于说明MVP设计来说已经足够了。1.1.3MVVM设计模式实现MVVM模式,并不是移动时代来临以后特有的,它起初的应用是微软的WPF(windowsvista用户界面框架),所以它并不新鲜,但是,引入到了移动端,它的重要性举足轻重。简单一句话是,相对于MVP和MVC,它彻底解耦了View层和下面的业务逻辑及数据层。MVVM的核心是”databinding”技术(数据绑定),在笔者看来,MVVM与其说是一种设计模式,笔者认为,不如说是一种前端解耦的解决方案更为妥当。关于MVVM,在Android里是需要一个特殊的lib库支持,才能实现MVVM的架构设计模式,这个lib在2015年5月googleIO发布,并已集成到了Androidstudio中,建议是读者可以直接参考googleAndroidDeloper官网的Databinding部分。本篇以android端的实现为例子介绍如何一步一步实现MVVM,权当做读者的快速上手文档。仍然以上面我们已经实现了的简易APP为例,不清楚的看第一章哟~构建前提是你的AndroidStudio升级到了1.3版本及以上(相信eclipse肯定也支持MVVM的构建,但是毕竟eclipse的开发方式逐步被Androidstudio替代,并且你的工程可以很容易从eclipse迁移到Androidstudio,鉴于此,使用studio说明MVVM的构建是OK的)第一步,设置AndroidStudio,打开Preferences-Appearances&Behavior-Updates-设置AutomaticallyCheckupdatesfor改为CanaryChannel。这个原因是MVVM毕竟在Android还算新的东西,并不完美,开启这个可以最快获取google发布的最新预览版,但可能会遇到BUG。图4AndroidStudio设置第二步,配置databinding环境,databinding是一个依赖库,他支持Android2.1及以上版本,但需要一定的配置。具体配置为,在gradle构建文件中配置如下:dependencies{classpathcom.android.tools.build:gradle:1.2.3classpathcom.android.databinding:dataBinder:1.0-rc0}在每一个想使用databinding的module中添加如下:applyplugin:'com.android.application'applyplugin:'com.android.databinding'触发sync,等待Androidstudio,自动配置相关环境。这个时间有点长,建议是翻下墙。如上配置后,就可以开始正式的开发工作了,本文所有改动仍然是实现,上一章在MVP结构下构建的APP,在上一章中,虽然初步实现了View与业务逻辑解耦,但是每种不足的是Activity仍然遗留了大量代码,譬如view内容变化、事件监听等,databinding其实就是为了解耦这部分工作而存在的,实现了databinding的APP,这些操作可以直接在xml中配置实现,并且这种模式下,是支持条件判断的。相对上一章没有列出的layout,在MVVM中,上一章中的layoutXML会长成如下样子:layoutxmlns:android==usertype=com.baidu.msg.base.User/variablename=vModeltype=com.baidu.msg.handlers.viewModel//dataLinearLayoutandroid:id=@+id/containerandroid:layout_width=match_parentandroid:layout_height=match_parentandroid:orientation=verticalEditTextandroid:id=@+id/idandroid:layout_width=match_parentandroid:layout_height=wrap_contentandroid:hint=输入idandroid:text=@{user.getId()}android:inputType=number/EditTextandroid:id=@+id/firstandroid:layout_width=match_parentandroid:layout_height=wrap_contentandroid:hint=interfirstnameandroid:text=@{user.getFirstName()}android:inputType=text/EditTextandroid:id=@+id/lastandroid:layout_width=match_parentandroid:layout_height=wrap_contentandroid:hint=interlastnameandroid:text=@{user.getLastName()}android:inputType=text/Buttonandroid:id=@+id/saveandroid:layout_width=match_parentandroid:layout_height=wrap_contentandroid:text=saveandroid:onClick=@{vModel.onClickButton}/Buttonandroid:id=@+id/loadandroid:layout_width=match_parentandroid:layout_height=wrap_contentandroid