时间:2021-05-20
原由
移动开发中,随着项目不断的跌代,需求越来越复杂后。项目工程也越来越庞大。那么此时的分module的开发,则是必然的选择了。在最终的组件化之路上,不妨把单一工程比如石器时代,那么接下来简单的拆分工程分多个moudle开来就是铜器时代。
铜器时代之简单分module
演进
由于从复杂的单工程拆分了多个module了,达到了代码及资源的初步的隔离,或需求模块的开发人员,开始专注于自己的需求模块module的开发了。但是随着部分需求有相关性,需要相互调用时。那么问题来了,在AXXX module中
api project(':BXXX')而在BXXX module中
api project(':AXXX')这时出现了相互依赖,首先编译器会能不过,会出现Circular dependency,循环相互依赖的问题,这是绝不允许的。
为了解决上述的问题,将AXXX module与BXXX module需要对外提供服务能力支持的,进行封装与抽象。将需要对外暴露接口/协议地方,对其抽象出接口出来。把些这接口独立放在BaseXXXX module中,这样AXXX module与BXXX module,都分别去
api project(':BaseXXXX')通过BaseXXXX中间module通信去解决AXXX module与BXXX module相互依赖调用通信。
初步的解决方法
为了在BaseXXXX module中,搭建起AXXX module与BXXX module相互通信的桥梁,可以在BaseXXXX module 定义一个通信标识接口:
/** * * 跨module通讯的 标识 interface接口 */public interface IModuleApi {}然后主要通过ModuleApiHelper进行通信
public class ModuleApiHelper { private static Map<Class<? extends IModuleApi>,IModuleApi> moduleApiMap = new HashMap<>(); private static Map<Class<? extends IModuleApi>,List<IModuleApi>> moduleApiListMap = new HashMap<>(); /** * 跨module 注册进 IKWModuleApi接口,及实现 * 通常可以在 其它的module中 注册此接口的实现,在用的module中getModuleApi拿到接口实现 * 这样,用的module 不是 必须依赖compile其它module了 * @param clazz * @param iModuleApi */ public static void register(Class<? extends IModuleApi> clazz, IModuleApi iModuleApi){ if (null != iModuleApi && null != clazz){ moduleApiMap.put(clazz, iModuleApi); } } public static void unregister(Class<? extends IModuleApi> clazz){ if (moduleApiMap.containsKey(clazz)){ moduleApiMap.remove(clazz); } } public static void register2List(Class<? extends IModuleApi> clazz, IModuleApi iModuleApi){ if (null != iModuleApi && null != clazz){ if (moduleApiListMap.containsKey(clazz)){ List<IModuleApi> iModuleApis = moduleApiListMap.get(clazz); iModuleApis.add(iModuleApi); }else{ List<IModuleApi> iModuleApis = new ArrayList<>(); iModuleApis.add(iModuleApi); moduleApiListMap.put(clazz, iModuleApis); } } } public static void unregister2List(Class<? extends IModuleApi> clazz){ if (moduleApiListMap.containsKey(clazz)){ moduleApiListMap.remove(clazz); } } public static void unregisterAll(Class<? extends IModuleApi> clazz){ unregister(clazz); unregister2List(clazz); } public static <T extends IModuleApi> List<T> getModuleListApi(Class<T> clazz){ if (null != clazz){ if (moduleApiListMap.containsKey(clazz)){ List<IModuleApi> iModuleApis = moduleApiListMap.get(clazz); return (List<T>) iModuleApis; }else{ return null; } }else{ return null; } } /** * 获取注册绑定过来的IKWModuleApi 实现 * @param clazz * @param <T> * @return */ public static <T extends IModuleApi> T getModuleApi(Class<T> clazz){ if (null != clazz){ if (moduleApiMap.containsKey(clazz)){ return (T) moduleApiMap.get(clazz); }else{ return null; } }else{ return null; } }}这样比如在AXXX module中将原有AServiceData类是如下的:
public class AServiceData { public String getSomeData(){ return "this is some data"; } public void sayHello(){ System.out.println("hello"); }}改造成
public interface IAServiceData extends IModuleApi { String getSomeData(); void sayHello();}public class AServiceData implements IAServiceData{ @Override public String getSomeData(){ return "this is some data"; } @Override public void sayHello(){ System.out.println("hello"); }}将IAServiceData接口定义在BaseXXXX module 中。然后AXXX module中进行register相应的服务
public class AModuleService { public void init(){ ModuleApiHelper.register(IAServiceData.class,new AServiceData()); }}这样调用AModuleService的init方法,即可对IAServiceData服务进行注册了。然后即下来,在BXXX module中进行getXXX得到服务即可调用相应的方法了.
在任何需要此服务的方法可如下调用:
IAServiceData iaServiceData = ModuleApiHelper.getModuleApi(IAServiceData.class);注意
1> register注册时机,需要越早越好,一般建议在各module的有类似的application的onCreate时注册最好。
2> IModuleApi与ModuleApiHelper,和各extends继承IModuleApi接口的接口,需要放在中间通信BaseXXX Module中。各需要通信的module去 compile/api BaseXXX Module即可。
问题
为了保证IModuleApi接口注册有效,需要越早越好进行注册。这样随着项目越来越复杂,需要通信的地方越来越多。统一的ModuleApiHelper,注册的地方将越来越多带的问题也多起来。
1> 注册Map容器占用的内存不断的增多。
2> register注册的地方不统一,有些放在各module的类Application的onCreate中,有些可能是放在其它的类中.
3> 不支持ui页面的跳转,由AXXX module的AxxActtivy页面跳转到BXXX module的BxxActivity页面中。
4> 不支持多进程中应用。
为了解决上述问题,引入了蒸汽时代之ARoute到来。
蒸汽时代之ARoute
由于遍幅的原因,总体概述不详细细述ARoute,下遍再剖析ARoute。总体来说在多module通信中解决了:
1> 解决了ui页面的跳转问题。
2> 根据需要进行register的问题,且register通过静态注解来的,所以register地方统一比如容易维护。
但是依然不能解决多进程中的应用。
电器时代之Andromeda
Andromeda解决了多进程,跨进程ipc之间的通信过程,同样也支持单进程的通信...
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
EventBus可以很方便地进行各组件间的通信,解耦性更强,比广播更好用。EventBus3简介EventBus是一种为了优化Android组件之间事件传递的解
React组件化思想受到越来越多开发者的关注,组件化思想帮助开发者将页面解耦成一个一个组件,代码更加模块化,更易扩展。而目前流行的后端模板引擎如ejs,swig
【1】遮罩层:承载内容,管理样式布局。【2】内容层:控制遮罩层的显示与否。遮罩层和内容区之间应该解耦。遮罩层和内容区之间应该解耦。遮罩层和内容区之间应该解耦。遮
前后端分离的开发模式,正是将前后端代码进行解耦,使得项目可以使用模块化的开发模式,前端代码使用组件便可以进行代码复用,后端代码使用经典三层架构使得逻辑清晰。这样
spring框架的优点是一个轻量级笔记简单易学的框架,实际使用中的有点优点有哪些呢!1.降低了组件之间的耦合性,实现了软件各层之间的解耦2.可以使用容易提供的众