Android组件管理新模式 -- Android Build Kit之组件配置管理

940 阅读5分钟

abkit(Android Build Kit)是一个Android组件化组件管理工具集,它是一个gradle插件,内部包含一些组件管理工具。使用示例请参考项目servicepool

  1. Android版本管理
  2. Module打包成aar/jar上传到maven仓库
  3. 组件配置管理(重点功能)
  4. 其他零碎功能

abkit接入方法请查看项目readme。本文介绍的是abkit最重点的功能 —— 组件依赖管理

模块化/组件化开发过程中,一旦组件多起来以后,组件的依赖管理会变得繁琐。

  1. 由于组件相互依赖的关系,我们通常不能明确当前用的是组件的哪个版本,这常常使我们困惑(如fastjson可能被很多库引用,最终使用的是哪个版本,并不明确)
  2. 我们常常会把项目打成aar/jar包,上传到maven仓库, 开发时就有project和远程aar两种依赖方式。这两种方式的使用和切换过程也会有很多麻烦
  3. 一个远程aar组件被很多个模块依赖,当这个aar组件版本升级后,需要查找所有的模块是否有依赖这个aar组件并升级它的版本。即使这样还是有可能无法精确的修改这个aar组件版本
  4. 当我只是想临时禁用掉某个组件来调试时,这个组件可能被太多的模块依赖导致操作异常繁琐
  5. 如果项目中有几十个上百个组件, 当前我只想调试某一个组件或几个组件,难道我需要把这几十个甚至上百个组件全部装载起来吗?

带着上面的问题,下面介绍这种新的组件依赖管理模式:

第一步,在settings.gradle中使用SettingsInject注入,用modules.gradle来接管settings.gradle!!!

import chao.android.gradle.plugin.api.SettingsInject  //会报红,编译时不报错就不影响使用
SettingsInject.inject(getSettings(), getGradle())

include ":app"

接管settings.gradle后,settings.gradle原有功能不受影响,还可以继续使用。只是扩展了一个新的配置脚本modules.gradle。

第二步, 在settings.gradle同级目录下新增modules.gradle,modules.gradle使用如下方式来配置modules:

module("servicepool") //servicepool是名称, 可以自由定义
    .project(":servicepool") // ":servicepool"是project名称
    .remote("chao.java.tools:servicepool:1.0.0")  // 与模块":servicepool"对应的远程aar/jar的名称
                                                  // 无论在dependencies引用时"chao.java.tools:servicepool"的版本号是什么,最终使用的都是这里设置的版本号
    .include()      // include()表示当前使用project(":servicepool")而不是远程依赖"chao.java.tools:servicepool:1.0.0"。
                    // 如果不调用include()方法,会使用远程依赖"chao.java.tools:servicepool:1.0.0", 并且":servicepool"不会被装载到项目
                    // .project()和.remote()至少有其中一个
    .disabled() // 禁用当前module。 这在想要临时禁用掉某个module时非常有用 

module("fastjson")
    .remote("com.alibaba:fastjson:1.1.68.android")
    .disabled()

module("servicepool_android")
    .project(":servicepool-android")
    .remote("chao.java.tools:servicepool-android:1.0.0")
//    .include()  不调用include(),将会使用远程依赖 "chao.java.tools:servicepool-android:1.0.0"
    

modules.gradle可以通过链式结构来配置一个module

  1. 以module方法开始,参数为module名称,名称可以自由定义。
  2. remote方法定义了一个远程依赖,默认使用远程依赖
  3. project()方法表示当前module定义了一个project,project必须使用include()方法后才会装载并使用
  4. include()方法表示装载一个project, 操作等价于settings.gradle中的include。 调用了include(),将使用project依赖而不是remote依赖
  5. disabled()方法表示禁用当前module, module被禁用后,module名称依然可以在build.gradle中被引用,但是实际引用的是一个空组件。

这样操作的好处是module的所有配置(名称,版本,类型)都收敛到了一个点。更简洁,管理起来更方便

modules配置好以后就可以在build.gradle中被引用了。

第三步, 在app或者其他module的dependencies{}中引入依赖。

dependencies {
    implementation servicepool          // servicepool是modules.gradle中定义module的名称,注意没有双引号
    implementation servicepool_android  
    
    api fastjson                        // 第二步中, fastjson调用了disabled(), fastjson将不会被引入到依赖,
                                        // 相当于这一条不存在,这在想要临时禁用掉fastjson时非常有用
                                        
    implementation 'chao.java.tools:servicepool:1.1.0'  // 由于modules.gradle中已经配置了servicepool的版本号为1.0.0, 最终依赖servicepool的版本将会是1.0.0,而不是1.1.0
}

第四步, modules.gradle文件是默认的配置文件,也可以在gradle.properties、plugin.properties或者local.properties中通过modules.gradle.file属性手动指定具体使用哪个文件做为modules的配置文件

modules.gradle.file=sample.gradle

接上面的第5个问题,如果项目有100多个project,而此刻我只想调试project(":sample"), 而sample依赖project(":sampleLib"),我们只需要在sample.gradle中做配置

module("sample").project(":sample").include()

module("sampleLib").project(":sample_lib").include()

...

同步以后, 只会有sample和sampleLib两个project会被引入到工程。这样将能减少gradle编译时间并大大提高调试效率

总结

modules.gradle使用新的方式来装载projects,modules中配置的module不需要再在settings.gradle中使用include引入。

接管settings.gradle前装载一个project

/**
 * settings.gradle中装载
 */
include ":servicepool"
/**
 *  module的build.gradle中引入
 */
 
 ...
 dependencies {
    implementation project(":servicepool")
 }

接管settings.gradle后,装载一个project

/**
 *  modules.gradle 中配置和装载
 */

module("servicepool").project(":servicepool").include()
/**
 *  module的build.gradle中引入
 */
 
 ...
 dependencies {
    implementation servicepool  //使用配置的名称即可
 }

abkit的组件依赖管理模式最大的好处就是将组件的配置收敛到modules.gradle里,方便统一装载和依赖:在build.gradle的depencencies{}中引用时,直接引用modules.gradle中配置的module名称即可。如果是远程组件, 组件的版本号可以明确就是modules.gradle中module配置的版本号。module可以自由的在project依赖和远程aar依赖之间切换。很容易禁用或启用某个module。