最近Google正式推出AS3.0版本,同时gradle插件也升级为3.0.0,目前各大开源库都在作gradle3.0.0的兼容,我也把获得开源的组件化方案AndroidComponent进行了升级,结论是:DDComponent在gradle3.0上是没有兼容问题的,能够直接使用。关于如何迁移到gradle3.0.0,请参见官方迁移指南。html
虽然没有兼容问题,但在升级的过程当中也收获了意外之喜,那就是发现gradle3.0.0对代码隔离的支持愈来愈好。为何对“代码隔离”这么关注呢?你们能够回顾前两篇文章Android完全组件化方案实践和Android完全组件化demo发布,在这两篇文章中提到的DDComponent组件化方案,被我冠以“完全”二字,虽然有些说大话,但主要是为了强调DDComponent与以前其余组件化方案的不一样之处就在于,DDComponent实现了组件之间的绝对隔离,不一样组件之间在代码开发阶段是彻底不可见的,是一种完全解耦的思想。为了实现这种隔离,我人为在编译和运行期作了一次判断和区分,既在编译期间(开发期间)组件之间没有任何依赖关系,但在打包和运行时,再偷偷添加依赖。具体能够参见前两篇文章和github源码。android
不得不说,当时这种实现是无可奈何,我原本想直接使用gradle提供的功能来作这种隔离,其实gradle也的确提供一个相似的功能,那就是apk依赖语法,其做用就是保证依赖库只在运行期间对外可见,但在编译期间是不可见的。按说这已经知足个人要求了,可是遇到了一个坑:在gradle2.+版本,apk依赖只能是jar,不能是aar,可是咱们的组件由于含有各类资源,输出产物就是aar!因此最终选择了放弃apk这种语法。git
而在最新的gradle3.0.0上,apk被替换为runtimeOnly语法,其做用仍是同样的,可是我发现runtimeOnly能够添加aar依赖!这的确让我很兴奋,这不就是我求之不得的功能吗?有了这个尚方宝剑,组件化的方案就能够作的更薄了啊。因而我对在获得app上进行了实验,结论是:runtimeOnly的确能够解决一些问题,可是还不够。下面我从代码隔离、资源隔离和调试切换(单独和集成)三个方便仔细阐述,也顺便再讲一下DDComponent所能实现的功能。github
在讲代码隔离以前,先大体看一下gradle3.0.0对添加依赖的语法变化。api
首先compile被废弃了,而是分红了两个:implementation和api,其中api与以前的compile功能基本一致,再也不赘述;implementation就比较高级了,其做用就是,使用implementation添加的依赖不会再编译期间被其余组件引用到,但在运行期间是彻底可见的。这也是一种代码隔离。举个例子,bash
组件A依赖lib1,既A implementation lib1
组件B依赖组件A,既B api A
复制代码
在gradle3.0.0以前,B是彻底能够引用到lib1里面的类的,可是如今B在编译期间就作不到了,只能在运行期能够。这种思想有点相似于“下属的下属不是你的下属”的思想。可是这种隔离在组件之间是不起做用的,在上面的例子中A的全部类对B仍是彻底可见的,也就是没有作任何隔离的。不过implementation的确是一种有效减小编译时间的方式,仍是上面的例子,lib1发生了变化,如今只须要编译A就能够了,而在以前B有可能也使用到了lib1,因此须要同时编译B和A。按照官方建议,大部分状况下都应该使用implementation来进行添加依赖。app
此外还有两种变化,原来的apk语法被runtimeOnly取代,provided被compileOnly取代,其做用仍是没变。上文也讲了,runtimeOnly有个极大的改动就是能够支持aar了,可是compileOnly仍是只能支持jar!ide
先作一个小结,目前gradle3.0.0的四种语法的功能和代码隔离效果见下图:组件化
从上图能够看出,在代码隔离效果上,runtimeOnly的效果是最好的!可是就能够直接使用了吗,答案是否认的。gradle
在前面的文章中,一直在强调代码隔离,其实组件之间的彻底隔离还有一层就是资源隔离,不然仍是容易形成组件之间的耦合。这个在文章的“单独调试”章节中提到了一句,就是每一个组件都须要指定一个资源前缀resourcePrefix,以免集成后资源名冲突的问题。也就是说,一个完全的组件化不只要作到代码不能直接引用,资源也是不能引用的!
可是runtimeOnly目前还作到资源隔离,我在DDComponent的开源库上作了试验,app经过runtimeOnly引用sharecomponent组件,虽然sharecomponent的代码是不可见了,可是资源仍是能够被app直接使用的并能成功运行。
从这一点上看,直接替换成runtimeOnly是不行的,为了达到这种效果,目前仍是须要像DDComponent同样,人为的加一层控制,因此从组件化方案的角度上看并无变的更薄,不过幸亏DDComponent已经很简单了,有必定的gradle基础的人能够比较容易的理解。
除了上面说的资源隔离致使不能直接用runtimeOnly以外,还有一个使用上的问题须要解决,这也是DDComponent中compbuild插件提供的一个功能:自动切换单独调试和集成调试。在单独调试时,组件是一个application工程,其输出产物是apk文件,而在集成调试时,被依赖的组件是一个library工程,其输出产物是aar文件。对于runtimeOnly来讲,对aar和jar是支持的,可是不能支持apk,因此若是想在单独调试和集成调试之间切换的话,须要人工修改runalone配置并修改build.gradle配置文件,而后还须要sync以后才能生效,这种修改是至关繁琐的。
在DDComponent中,这个问题的解决是经过“智能”识别当前要调试的组件来解决的,对于要调试的组件将其设置为application工程,而将其依赖的其余组件默默修改成library工程,这种修改是即时生效的,对开发者是彻底透明的。开发者直接点击AS的run功能区就能够随意的调试任意组件。AS的run功能区的图以下:
综上所述,咱们对DDComponent和gradle3.0.0作几点总结: (1)升级到gradle3.0.0以后,能够继续使用DDComponent,不须要专门作兼容 (2)gradle3.0.0提供了implementation和runtimeOnly两种语法,它们都能实现必定程度的代码隔离效果,建议你们在从此优先使用 (3)implementation和runtimeOnly目前还在资源隔离和调试切换上还能知足组件化的要求,因此仍是须要使用DDComponent提供的彻底隔离和随意切换功能。
在DDComponent的源码中我增长了gradle3.0.0分支,依赖语法作了相应的替换,欢迎你们继续支持“获得”app出品的组件化方案,源码地址:https://github.com/mqzhangw/AndroidComponent