android module解耦组件化总体概述(推荐)
原由
移动开发中,随着项目不断的跌代,需求越来越复杂后。项目工程也越来越庞大。那么此时的分module的开发,则是必然的选择了。在最终的组件化之路上,不妨把单一工程比如石器时代,那么接下来简单的拆分工程分多个moudle开来就是铜器时代。
铜器时代之简单分module
演进
由于从复杂的单工程拆分了多个module了,达到了代码及资源的初步的隔离,或需求模块的开发人员,开始专注于自己的需求模块module的开发了。但是随着部分需求有相关性,需要相互调用时。那么问题来了,在AXXXmodule中
apiproject(':BXXX')
而在BXXXmodule中
apiproject(':AXXX')
这时出现了相互依赖,首先编译器会能不过,会出现Circulardependency,循环相互依赖的问题,这是绝不允许的。
为了解决上述的问题,将AXXXmodule与BXXXmodule需要对外提供服务能力支持的,进行封装与抽象。将需要对外暴露接口/协议地方,对其抽象出接口出来。把些这接口独立放在BaseXXXXmodule中,这样AXXXmodule与BXXXmodule,都分别去
apiproject(':BaseXXXX')
通过BaseXXXX中间module通信去解决AXXXmodule与BXXXmodule相互依赖调用通信。
初步的解决方法
为了在BaseXXXXmodule中,搭建起AXXXmodule与BXXXmodule相互通信的桥梁,可以在BaseXXXXmodule定义一个通信标识接口:
/** * *跨module通讯的标识interface接口 */ publicinterfaceIModuleApi{ }
然后主要通过ModuleApiHelper进行通信
publicclassModuleApiHelper{ privatestaticMap,IModuleApi>moduleApiMap=newHashMap<>(); privatestaticMap ,List >moduleApiListMap=newHashMap<>(); /** *跨module注册进IKWModuleApi接口,及实现 *通常可以在其它的module中注册此接口的实现,在用的module中getModuleApi拿到接口实现 *这样,用的module不是必须依赖compile其它module了 *@paramclazz *@paramiModuleApi */ publicstaticvoidregister(Classclazz,IModuleApiiModuleApi){ if(null!=iModuleApi&&null!=clazz){ moduleApiMap.put(clazz,iModuleApi); } } publicstaticvoidunregister(Classclazz){ if(moduleApiMap.containsKey(clazz)){ moduleApiMap.remove(clazz); } } publicstaticvoidregister2List(Classclazz,IModuleApiiModuleApi){ if(null!=iModuleApi&&null!=clazz){ if(moduleApiListMap.containsKey(clazz)){ List iModuleApis=moduleApiListMap.get(clazz); iModuleApis.add(iModuleApi); }else{ List iModuleApis=newArrayList<>(); iModuleApis.add(iModuleApi); moduleApiListMap.put(clazz,iModuleApis); } } } publicstaticvoidunregister2List(Classclazz){ if(moduleApiListMap.containsKey(clazz)){ moduleApiListMap.remove(clazz); } } publicstaticvoidunregisterAll(Classclazz){ unregister(clazz); unregister2List(clazz); } publicstatic List getModuleListApi(Class clazz){ if(null!=clazz){ if(moduleApiListMap.containsKey(clazz)){ List iModuleApis=moduleApiListMap.get(clazz); return(List )iModuleApis; }else{ returnnull; } }else{ returnnull; } } /** *获取注册绑定过来的IKWModuleApi实现 *@paramclazz *@param *@return */ publicstatic TgetModuleApi(Class clazz){ if(null!=clazz){ if(moduleApiMap.containsKey(clazz)){ return(T)moduleApiMap.get(clazz); }else{ returnnull; } }else{ returnnull; } } }
这样比如在AXXXmodule中将原有AServiceData类是如下的:
publicclassAServiceData{ publicStringgetSomeData(){ return"thisissomedata"; } publicvoidsayHello(){ System.out.println("hello"); } }
改造成
publicinterfaceIAServiceDataextendsIModuleApi{ StringgetSomeData(); voidsayHello(); } publicclassAServiceDataimplementsIAServiceData{ @Override publicStringgetSomeData(){ return"thisissomedata"; } @Override publicvoidsayHello(){ System.out.println("hello"); } }
将IAServiceData接口定义在BaseXXXXmodule中。然后AXXXmodule中进行register相应的服务
publicclassAModuleService{ publicvoidinit(){ ModuleApiHelper.register(IAServiceData.class,newAServiceData()); } }
这样调用AModuleService的init方法,即可对IAServiceData服务进行注册了。然后即下来,在BXXXmodule中进行getXXX得到服务即可调用相应的方法了.
在任何需要此服务的方法可如下调用:
IAServiceDataiaServiceData=ModuleApiHelper.getModuleApi(IAServiceData.class);
注意
1>register注册时机,需要越早越好,一般建议在各module的有类似的application的onCreate时注册最好。
2>IModuleApi与ModuleApiHelper,和各extends继承IModuleApi接口的接口,需要放在中间通信BaseXXXModule中。各需要通信的module去compile/apiBaseXXXModule即可。
问题
为了保证IModuleApi接口注册有效,需要越早越好进行注册。这样随着项目越来越复杂,需要通信的地方越来越多。统一的ModuleApiHelper,注册的地方将越来越多带的问题也多起来。
1>注册Map容器占用的内存不断的增多。
2>register注册的地方不统一,有些放在各module的类Application的onCreate中,有些可能是放在其它的类中.
3>不支持ui页面的跳转,由AXXXmodule的AxxActtivy页面跳转到BXXXmodule的BxxActivity页面中。
4>不支持多进程中应用。
为了解决上述问题,引入了蒸汽时代之ARoute到来。
蒸汽时代之ARoute
由于遍幅的原因,总体概述不详细细述ARoute,下遍再剖析ARoute。总体来说在多module通信中解决了:
1>解决了ui页面的跳转问题。
2>根据需要进行register的问题,且register通过静态注解来的,所以register地方统一比如容易维护。
但是依然不能解决多进程中的应用。
电器时代之Andromeda
Andromeda解决了多进程,跨进程ipc之间的通信过程,同样也支持单进程的通信...
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。。