关于模块化
关于模块化就不过多介绍了,感兴趣的可以看一下Android 模块化探索与实践和安居客 Android 项目架构演进这两篇文章,这两篇文章是我认为写的比较好的。现在我来主要闲聊一下模块化开发中遇到的一些问题和自己总结的经验。
遇到的问题
在看了很多关于模块化开发的文章以及案列后,在公司的一个新项目中我开始尝试模块化的开发。把复杂的功能拆分成一个个的模块。原以为会很顺利,但在开发中却遇到了很多文章上都没有提过的问题。以下是第一次使用模块化开发中遇到的一些问题,这些问题虽然不是很严重的问题,但对于初次使用的人也会造成一些小小的困扰,这里写出来,供大家参考。
1.资源文件引用问题和实体类引用问题
按照思路,每个模块之间是独立的,可以打包成一个app的,那么每个模块之间在开发阶段就应该尽可能的独立。可是当一两个模块开发完成之后,会发现每个模块之间,都存在重复和冗余的资源文件。比如,这张图片模块A里有了,模块B里也有,但都是同一张。那么这个时候就有两种解决方法。第一种:不管冗余的资源文件。第二种把A模块和B模块里的资源文件都删了,把这个共同的资源文件放到他们都可以给访问的BaseModule里。可以看出,不管是哪种,都不尽如人意。同理,实体类也是,实体类的主要问题是不同模块之间的实体类很可能必须是要一样的,这也是后期修改的需要。例如在划分模块的时候,不同模块之间的实体类需要一样,为了后期维护方便,只能采取上面所说的第二种方法。但就算付出了时间和精力让架构更清晰和健壮,也会带来第二个问题。
2.BaseModule过大
按照上面两篇文章的说法,所有的模块都会依赖于一个BaseModule,而我们的AppModule则只是这些其余Module的入口。如下图所示:
这只是截取了一部分来显示。我想说的是,为了能够在不同模块之间共用资源文件和实体类,我们不得不把很多东西放到BaseModule里,这会让BaseModule越来越大。或许有些人觉得这是正常的,但这会导致一些功能简单,需要不断复用的模块无法依赖BaseModule。例如PayModule(支付模块),ShareModule(分享模块)等需要在其他项目中可以直接拿来用的模块,无法直接引用BaseModule里的一些实体,或者封装好的网络请求方法。因为如果一旦引用了,就必须把庞大的BaseModule带上。违背了模块化就是要让一些模块可以不断复用的初衷。
3.模块之间的相互通讯的一些问题
使用AS的时候,是不允许互相依赖的。比如我的appModule依赖了TicketModule,那么TicketModule是不能依赖appModule的。那么当我想要从TicketModule中打开app中的某个Activity的时候,我是无法直接打开的。因为你拿不到appModule里的任何东西。所以这里你有两种选择,使用隐式Intent或者使用路由框架。这里推荐一下阿里巴巴开源的路由框架ARouter,功能简单但够用。但这样也是存在问题的。ARouter基于注解实现,看上去十分方便简洁。但很多时候你会不知道哪些地方你应该直接跳转,哪些地方应该使用路由。并且ARouter存在一个问题,你用ARouter进行类似startActivityForResult的操作的时候,你当前Activity里的Fragment是接收不到onActivityResult的,需要自己去显示调用fragment的onActivityResult,原因在于requestCode那里,感兴趣的可以自己去看源码,这里就不多提了。总结一下就是,当你使用模块化开发,你不得不考虑模块间的跳转问题,而模块间的跳转问题又存在如何规范和框架本身的一些问题。
一些自己的经验
在这里,分享一些自己的经验给即将或者已经在使用模块化开发的人
1.熟悉和理清项目
这也是最重要的,不单单是对项目的逻辑进行梳理,当拿到功能图或者结构图时,除了注意项目的逻辑,还有其中的一些资源文件,可能的实体类自己心中应该有一些把握,可以省去之后的很多麻烦。
2.对功能性强的模块,可以存在一些冗余
如上所说,例如PayModule(支付模块),ShareModule(分享模块)等,虽然BaseModule里已经封装好了网络请求的相关方法,但依然可以自己写一些基础的方法在这两个模块中,虽然看似冗余,但可以让这两个模块不依赖于庞大的BaseModule,让这两个模块真正的达到复用的目的。
3.规范模块间跳转的约定
多人开发的时候,应该在开发之前对模块间的跳转做一个约定,这样可以省去后期很多的代码维护和梳理的时间。以及在开发之初对跳转方法的选型,应该结合项目来考虑,很多时候,隐式跳转其实也够用了。至于使不使用路由框架,也应该结合项目本身来进行思考
最后,闲聊一下MVP以及MVVM
本篇博文开头供大家参考的文章中多次提到了MVP,并把MVP作为模块与模块之间的约定和共性。要求每个模块都应遵循MVP的开发规范。事实上在我的项目中我也选择了MVP作为这个项目的主要开发模式。事实上MVP结合RXJAVA可以很好的仿制内存泄漏,以及MVP模式下,很多接口和Presenter可以服用。但很多人容易进入一个误区,即选择了MVP就不应该再使用MVC或者MVVM,我认为这是错的。MVP,MVC,MVVM都只是一种设计模式,本质上都是让代码更容易维护。那么基于这样的诉求,就不应该过多的纠结于该用哪种。比如一个界面里有很多需要填写的内容,这个时候可以考虑使用mvvm。而一个界面如果有很复杂的逻辑交互和网络请求,那么应该使用mvp模式。而如果一个界面同时兼具以上两种,那么一个界面可以同时使用mvp和mvvm也是可以的。填充数据使用mvvm而复杂的网络请求使用mvp。总结一下就是,不应该拘泥于设计模式,这会让简单的代码变得复杂。
知无不言,言无不尽,言者无罪,闻者足戒
以上就是是我开发中遇到的问题和看法,供大家参考。