这样处理过后便可以实现一般情况下单独运行,特殊情况下(执行uploadComponent
)可以打包成为aar供其他module依赖。
一般情况下所有承载业务的module都是application,而agp是无法依赖application的module的,因此直接依赖是不可行的,需要将module打包为aar上传到公共仓库,再通过依赖仓库内包的形式进行依赖。因此这个方案要额外一步手动upload,这也是目前发现的缺陷,不过计划中该操作可以通过脚本帮助简化。
代码资源隔离最主要的目的就是解除耦合,杜绝直接引用,方便模块插拔而不影响编译,理想情况下两个模块无任何耦合。实现隔离其实只需在开发期无法调用依赖module的代码即可,非常简单,在执行打包task(如assembleRelease
, bundleReleaseResource
)时再进行依赖。
但是实际中,让同一个应用内的两个模块没有任何直接应用所付出的维护代价还是比较大的,就以模块间通信来说,如果没有直接耦合,就必须通过base lib进行支持(Event或公有接口下沉),或者定义新的交互接口(类似网络交互)。前者需要在base lib内维护所有用于通信的内容,会导致base lib过分冗余;后者太过复杂,无论是开发还是执行效率都会有一定损失。因此一般情况下在可控范围内暴露一定的接口还是有必要的,供module间直接交互,在解藕和开发效率间做一个平衡。
继续上面的思路。编译插件提供了注解供调用者自己决定该暴露哪个接口。插件所做的处理就是将被注解的类,和其内部所有引用的类都暴露给外部。
首先来看如何找到所有类的引用类,又是众所周知,class文件内的常量池有一项为CONSTANT_Class_info
,该项表示的是类中对其他类或接口的符号引用,Code类型的Attribute_info
内就会使用这些常量,但是仅仅如此还是不够的——返回类型,参数,注解和范型都会有对其他类进行引用的情况,因此还需对这些进行处理。 如果使用Javassist做class结构的解析的话,CtClass#getRefClassess()
方法已经处理了前几种情况,具体的实现可以参照Javassist源码,这里主要说下如何处理范型的引用类型。
可能在大部分人的印象中&#x