这是本人第一次在csdn写博客,工作了几年,一直没有写博客的习惯。总感觉不喜欢把时间花在这上面,自己的经验积累或者总结,总会写一些标签类的东西。比如某某问题的解决,是在哪个项目中的哪些地方,当出了同样问题的时候,通过看代码可以想到当时解决问题的场景,不用再去捋一遍。
后来发现很多人都在做一些电子版的总结,那么我也来尝试一下,分享一下最近的一个项目。
1.多业务 模块分离 原因
目前Android开发世界里,各种框架五花八门,本人也接触过一部分框架,有褒有贬。且不说其他框架的好与坏,网上各大帖子都有赘述。该框架,也算是借鉴了一些热门框架加了一些个人的看法而成。
接下来就聊聊正题,接手了一个项目。项目类似钉钉,用于环卫类企业的内部员工使用,项目有即时通讯需求,基于地图的项目管理以及项目相关需求,有考勤物料事件等需求,组织架构人员信息需求等。基本可以分4个业务功能。但是其中一些功能,如即时通讯,组织架构人员等必然会在以后公司的其他需求中出现,为了保证后期新项目开发的方便快捷,本项目将这些业务功能以module形式分离开发,便于以后新项目功能的移植。
另外,由于我组开发人员较多,各个业务都分组开发,各组间对其他开发内容了解程度并不高,所以使用模块分离,接口开放的方式来进行开发,会提高一些业务间相互调用的便捷性和交流方便性。而且,当业务功能有所变化,也不至于牵一发动全身,完全不会影响到其他模块的代码。
2.多业务 模块分离 的基本思路
首先,模块分离的最基本需要,是要创建多个module来去承载不同的业务模块。纵向来看,项目分为入口module,业务module,基础module和SDKmodule。横向来看,每个业务由一个独立的module来承载。
一,library模块
自上而下来讲,我们首先从library层module开始,也就是SDKmodule。此module主要是作为第三方开源工具以及技术型的公共功能的容器,我们可以在此module中对第三方工具的版本进行控制,以及针对某些功能做一个封装,以工具类或者接口的形式提供给上层的module来使用。
这样有一个好处,我可以举个例子,在我之前做过的项目中,有关于一些基于地图功能的业务需求,一开始我们与百度地图进行了合作,项目中以sdk的形式接入了百度地图。于是在我们的业务代码中有很多关于地图的api的使用,部分逻辑代码严重依赖了sdk中的api。但是到了项目开发后期,公司忽然接入了和国外合作的业务,由于百度地图目前只能在国内很好的使用,在国外地图功能就不能很好的发挥作用,于是便重新寻找了地图合作商。这样一来,由于需要替换sdk,造成了业务代码需要大量的修改,从而耗费了一些时间。
以前也了解过滴滴的应用的地图解决海内外问题的办法(通过看帖子了解,如有出入,请私信我,我会及时做改正),滴滴采用了两套地图,国内为高德,国外为谷歌。在上层,他们的开发者对地图sdk做了进一步封装,通过某些方式对地图进行切换,以接口形式提供给业务代码开发者,虽然为不同地图,但是在业务开发者角度,他们只有一套api,不过在封装的过程中根据地理位置进行了切换。以这样的方式就解决了海内外地图不能互用的问题,当然,这个方式也解决了第三方sdk临时更换而要修改业务代码的问题。因此,个人认为library的module还是很有必要的。在library对所有第三方api进行封装,向上提供接口,将来如有服务商的更换,业务代码依然不受影响。
但是,这样的开发也要在真正编写代码前做好全面的准备。例如工具是否需要初始化,接口传参是否满足大部分需求,何如基于需求对api进行封装,异步类如何管理等等。包括,是否需要针对所有sdk或者第三方依赖的初始化啊等做一些统一的封装,一个方法处理大部分逻辑等。本人也只是在工作过程中一点点积累,一点点完善,我的思路还有很多问题,想和大家分享分享学习一些经验。
二,base模块
base模块呢,其实就是相对于比较针对项目的具体业务了,以及一些高效的和公共的功能封装。比如页面base,常量库,项目配置参数,数据库控制类,异步消息数据结构,网络框架封装,网络状态检测,server管理类,provider接口,aop注解与逻辑类,工具类,公共自定义widget等等。
常用的一些封装大家都比较熟悉,由于我的这个架构中,关于模块间的调用以及页面的跳转,使用了路由的机制。页面的跳转,fragment的实例获取,以及模块间交互的service实例获取,都以url的形式来执行。由于模块间没有相互依赖,所以base中的service管理,provider管理显得很重要,他们是作为模块间交互的基础和跳板。
另外还有一些常用的思维,比如某些基类使用build模式,链式调用,对项目中七七八八样式的弹框封装,网络框架基于ui的封装,日志平台的对接,适配啊等等。
其中,想说明一点,也不是什么技术性强的东西。在以前的开发过程中,有时候封装了一些很具体的Dialog,这样我觉得扩展性不高。何为具体的Dialog,就是只能用在某个业务的功能节点处,当在其他业务模式节点处要用到相似的弹框时,就还需要重新编写一套Dialog,如样式,弹出方式,展现形式,内容等等,看似有区别,其实代码大同小异。所以,个人认为,针对Dialog的封装,尽量做到扩展性强。如暴露出弹框内容url接口,可异步获取内容,暴露出布局填充接口,可自定义布局,暴露出view填充接口,暴露出弹框位置基于View等等。我们只对Dialog的弹出方式,或者说与内容无关的进行编写,其他全部以接口形式暴露出去,这样就可以做到Dialog的灵活使用。
其实也就是以Dialog的封装作为一个例子,个人比较喜欢这种思维方式和开发模式。可能也是因为公司项目多,很多项目中会有类似需求,不管是封装小控件,还是编写框架或业务,都喜欢做到可扩展,可移植。
三,业务模块 vc模式
业务模块,在思想上没有啥可说的,就是业务逻辑嘛。其中想说下vc模式。
再次先说明,vc模式,也是根据公司实际情况,人力物力,和自己的想法而成,和各位大神的先进思想还是差很多,求建议。
谷歌官方推荐的模式当然是很不错的,但是也得根据实际情况。我个人使用vc并且摒弃了m,也就是不严格的mvc模式,有这么几点考虑。
1.如果是使用mvp或vvm等目前较火的框架,根据个人以往的开发经验,我认为开发成本相对来说高一些,因为每一个业务点都要建立m,p等等,在我看来我觉得并不需要花这么多时间在这个上面。当然,这个项目框架也只是初级一些的框架,适合初学者或者刚入行的人练习使用。
2.严格mvc模式。
严格的mvc模式,分为三块,显示层,交互层,数据层。在以前的项目经验中,我个人认为这个模式特别好用,但后来发现,当公司工期在十分紧张的情况下,model和controller是可以合并的。不过呢,是在controller中以方法传参的形式把控制器模块和数据模块在一个类中区分开,这样也就减少了一个环节,相对来说,少一点点工作量。而逻辑上也不算乱,可以比较容易理清逻辑路线。
3.多业务 模块分离中其他细节
一,路由机制
项目中使用了路由机制,用来定位Activity,Fragment,以及模块间数据交互的provider。所有的页面跳转,fragment实例获取,provider调用,都通过路由url的方式来执行。
通过对对应类进行Route标记,就可以通过对应的url精准找到对应的页面或者实例。如此一来,我们无需通过import的形式去拿到需要类的引用,而是通过url,这样就实现了两个没有任何依赖的模块间的页面跳转和数据交互,也可以让各个模块独立起来,之间不必有联系,使模块相对独立,可拆解。
二,AOP
项目中使用了一些aop的思想,不过也只是一些基础的东西。项目中所有关于检查或者需要限制的东西我们统一通过此来实现。
本项目中,以AspectJ为基础,做了一些基于注解的功能。如,检查登陆跳转,权限检查,按钮单击,页面跳转判断等等。
可以看下检查登陆跳转:
通过注解和Aspect修饰的执行类就可以实现在执行某方法时做登陆检查的判断。不必要再在项目里写一些if else的判断。
另外,我在项目中通过把AspectJ与EasyPermission相结合做了通过注解执行动态权限请求的问题。
通过此方式,也把动态权限检查做的相对比较简单了一些。
三,provider机制
provider呢,主要用作需要抽离的功能方法,以及模块间数据交互的桥梁。
首先,我们需要在base模块中建立需要抽离的interface。然后在对应上层的业务模块中编写该interface的实现类,也就是抽象方法具体的实现内容。实现类使用Route注解进行修饰,便可以通过url的形式进行获取。
此为在base模块中建立的打开聊天页面的接口。
此为在对应业务模块中对接口的实现类。
通过此种方式便可以在模块间以url的形式进行数据交互,并且模块间不会有任何的引用依赖。使模块间相互独立,可随意拆解。
当拆解之后,返现找不到对应url的实例时,可以通过路由中的降级机制进行解决。
这就是一个简单的多业务的模块分离的初级框架,里面有很多想法可能已经不是很好,也希望码友能来吐槽,也希望可以帮助到一些需要的人。